private void DeleteBtn_Click(object sender, EventArgs e) { var btn = (RenderBtn <Track>)sender; Tracks.Remove(btn.Tag); var firstName = Tracks.FirstOrDefault()?.Name; DefaultTrackLeft.ReplaceAllValues(btn.Tag.Name, firstName); DefaultTrackRight.ReplaceAllValues(btn.Tag.Name, firstName); trackRemoves.Add(btn.Tag.Name); Invalidate(); }
/// <summary> /// Gets a track from the library matching the specified filename. /// </summary> /// <param name="filename">The filename.</param> /// <returns>The associated track, or null if it doesn't exist</returns> public Track GetTrackByFilename(string filename) { filename = filename.ToLower().Trim(); lock (Tracks) { var track = Tracks.FirstOrDefault(t => t.Filename.ToLower() == filename); if (track != null && !File.Exists(track.Filename)) { track = null; } return(track); } }
private void OnMessageMyMusicChanged(MessageMyMusicChanged message) { if (!message.AddedTracks.IsNullOrEmpty()) { foreach (var track in message.AddedTracks) { Tracks.Insert(0, track); } } if (!message.RemovedTracks.IsNullOrEmpty()) { foreach (var track in message.RemovedTracks) { Tracks.Remove(Tracks.FirstOrDefault(t => t.Id == track.Id)); } } }
/// <summary> /// Called after undo/redo to make sure that no deleted blocks or tracks are in the selection. /// </summary> public void SanityCheckSelections() { // TODO: once we have a better ObservableCollection, use RemoveAll for better performance for (int i = SelectedBlocks.Count - 1; i >= 0; i--) { var block = SelectedBlocks[i].GetModel(); if (!model.Blocks.Contains(block)) { SelectedBlocks.RemoveAt(i); } } if (!Tracks.Contains(SelectedTrack)) { // At this point, we don't really know where the selected track was, // so just go with the first one. SelectedTrack = Tracks.FirstOrDefault(); } }
private void NextPlayTrack(Track track) { if (Tracks.Count > 0) { Track nextTrack; var currentIndexTrack = Tracks.IndexOf(track); var nextIndexTrack = currentIndexTrack + 1; nextTrack = nextIndexTrack < Tracks.Count ? Tracks[nextIndexTrack] : Tracks.FirstOrDefault(); CurrentTrack = nextTrack; CurrentUri = nextTrack.Path; CurrentTrackName = nextTrack.FullName; SliderMinimum = SliderMaximum = SliderValue = 0.0; LoadedMode = MediaState.Play; } }
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length) { if (!IsWriting) { ErrorMessage = "Tried to write on a non-writable image"; return(false); } Track track = Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector && sectorAddress <= trk.TrackEndSector); if (track is null) { ErrorMessage = $"Can't found track containing {sectorAddress}"; return(false); } if (sectorAddress + length > track.TrackEndSector + 1) { ErrorMessage = "Can't cross tracks"; return(false); } if (data.Length % track.TrackRawBytesPerSector != 0) { ErrorMessage = "Incorrect data size"; return(false); } _dataStream. Seek((long)(track.TrackFileOffset + ((sectorAddress - track.TrackStartSector) * (ulong)track.TrackRawBytesPerSector)), SeekOrigin.Begin); _dataStream.Write(data, 0, data.Length); return(true); }
void OnContestLoaded(object sender, LoadedEventArgs <Contest> e) { if (e.Error != null) { this.ShowError(e.Error.Message); } else { this.contest = e.Result; foreach (var t in e.Result.Tracks) { var trackViewModel = new TrackViewModel(t); trackViewModel.AnonymousMode = this.AnonCommand.AnonymousMode; trackViewModel.PropertyChanged += (s, args) => this.dirtyFlag = true; this.Tracks.Add(trackViewModel); } SelectedTrack = Tracks.FirstOrDefault(t => !t.IsExcluded); } this.IsLoading = false; }
private async Task ExecuteFilterCommand(Page page) { if (IsBusy) { return; } var trackNames = new List <string>(Tracks.Select(t => t.Title)); if (trackNames.Count == 0) { return; } trackNames.Insert(0, "Show All"); if (Device.OS == TargetPlatform.Android) { DependencyService.Get <IDialogs>().DisplayActionSheet("Select Tracks", "Cancel", trackNames.ToArray(), which => { _selectedTrack = which == 0 ? null : Tracks[which - 1]; FilterSessions(_selectedTrack); }); //if show all pass null } else { string action = await page.DisplayActionSheet("Select Track", "Cancel", null, trackNames.ToArray()); if (action == "Cancel") { return; } _selectedTrack = Tracks.FirstOrDefault(t => t.Title == action); FilterSessions(_selectedTrack); } }
/// <summary> /// Remove roller from this belt. All TrackWheel components previously /// added to the <paramref name="roller"/> will be removed. /// </summary> /// <param name="roller">Roller to remove.</param> /// <returns>True if successfully removed, otherwise false (check console log).</returns> public bool Remove(GameObject roller) { if (roller == null || !m_rollers.Contains(roller)) { return(false); } var trackWheels = roller.GetComponents <TrackWheel>(); // This shouldn't happen when/if undo is working. if (trackWheels.Length == 0) { Debug.LogWarning($"Roller {roller.name} doesn't contain any TrackWheel instances."); return(false); } using (BeginResourceRequests()) { foreach (var trackWheel in trackWheels) { var track = Tracks.FirstOrDefault(subject => subject.Contains(trackWheel)); if (track == null) { Debug.Log("TrackWheel wasn't removed from any track but will be destroyed.", trackWheel); } else { AboutToChange(track); track.Remove(trackWheel); } DestroyObjectImmediate(trackWheel); } m_rollers.Remove(roller); } return(true); }
/// <summary> /// Gets the media track /// </summary> /// <param name="trackId">track identifier</param> /// <returns>the media track</returns> public MediaTrack?GetMediaTrack(string trackId) { return(Tracks?.FirstOrDefault(t => t.Id == trackId)); }
public bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag) { if (!IsWriting) { ErrorMessage = "Tried to write on a non-writable image"; return(false); } Track track = Tracks.FirstOrDefault(trk => sectorAddress >= trk.TrackStartSector && sectorAddress <= trk.TrackEndSector); if (track is null) { ErrorMessage = $"Can't found track containing {sectorAddress}"; return(false); } switch (tag) { case SectorTagType.CdTrackFlags: case SectorTagType.CdTrackIsrc: return(WriteSectorTag(data, sectorAddress, tag)); case SectorTagType.CdSectorSubchannel: { if (track.TrackSubchannelType == 0) { ErrorMessage = $"Trying to write subchannel to track {track.TrackSequence}, that does not have subchannel"; return(false); } if (data.Length % 96 != 0) { ErrorMessage = "Incorrect data size for subchannel"; return(false); } if (_subStream == null) { try { _subStream = new FileStream(_writingBaseName + ".sub", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } catch (IOException e) { ErrorMessage = $"Could not create subchannel file, exception {e.Message}"; return(false); } } _subStream. Seek((long)(track.TrackSubchannelOffset + ((sectorAddress - track.TrackStartSector) * 96)), SeekOrigin.Begin); _subStream.Write(Subchannel.Deinterleave(data), 0, data.Length); return(true); } default: ErrorMessage = $"Unsupported tag type {tag}"; return(false); } }
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } _dataStream.Flush(); _dataStream.Close(); _subStream?.Flush(); _subStream?.Close(); FullTOC.CDFullTOC?nullableToc = null; FullTOC.CDFullTOC toc; // Easy, just decode the real toc if (_fulltoc != null) { byte[] tmp = new byte[_fulltoc.Length + 2]; Array.Copy(BigEndianBitConverter.GetBytes((ushort)_fulltoc.Length), 0, tmp, 0, 2); Array.Copy(_fulltoc, 0, tmp, 2, _fulltoc.Length); nullableToc = FullTOC.Decode(tmp); } // Not easy, create a toc from scratch if (nullableToc == null) { toc = new FullTOC.CDFullTOC(); Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>(); toc.FirstCompleteSession = byte.MaxValue; toc.LastCompleteSession = byte.MinValue; List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>(); byte currentTrack = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { if (track.TrackSession < toc.FirstCompleteSession) { toc.FirstCompleteSession = (byte)track.TrackSession; } if (track.TrackSession <= toc.LastCompleteSession) { currentTrack = (byte)track.TrackSequence; continue; } if (toc.LastCompleteSession > 0) { sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack); } toc.LastCompleteSession = (byte)track.TrackSession; } byte currentSession = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { _trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); if (trackControl == 0 && track.TrackType != TrackType.Audio) { trackControl = (byte)CdFlags.DataTrack; } // Lead-Out if (track.TrackSession > currentSession && currentSession != 0) { (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150); (byte minute, byte second, byte frame)leadoutPmsf = LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last(). TrackStartSector); // Lead-out trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xB0, ADR = 5, CONTROL = 0, HOUR = 0, Min = leadoutAmsf.minute, Sec = leadoutAmsf.second, Frame = leadoutAmsf.frame, PHOUR = 2, PMIN = leadoutPmsf.minute, PSEC = leadoutPmsf.second, PFRAME = leadoutPmsf.frame }); // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC... trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xC0, ADR = 5, CONTROL = 0, Min = 128, PMIN = 97, PSEC = 25 }); } // Lead-in if (track.TrackSession > currentSession) { currentSession = (byte)track.TrackSession; sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber); (byte minute, byte second, byte frame)leadinPmsf = LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber)?.TrackEndSector ?? 0 + 1); // Starting track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA0, ADR = 1, CONTROL = trackControl, PMIN = (byte)track.TrackSequence }); // Ending track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA1, ADR = 1, CONTROL = trackControl, PMIN = endingTrackNumber }); // Lead-out start trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA2, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = leadinPmsf.minute, PSEC = leadinPmsf.second, PFRAME = leadinPmsf.frame }); } (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector); // Track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = (byte)track.TrackSession, POINT = (byte)track.TrackSequence, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = pmsf.minute, PSEC = pmsf.second, PFRAME = pmsf.frame }); } toc.TrackDescriptors = trackDescriptors.ToArray(); } else { toc = nullableToc.Value; } _descriptorStream.WriteLine("[CloneCD]"); _descriptorStream.WriteLine("Version=2"); _descriptorStream.WriteLine("[Disc]"); _descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length); _descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession); _descriptorStream.WriteLine("DataTracksScrambled=0"); _descriptorStream.WriteLine("CDTextLength=0"); if (!string.IsNullOrEmpty(_catalog)) { _descriptorStream.WriteLine("CATALOG={0}", _catalog); } for (int i = 1; i <= toc.LastCompleteSession; i++) { _descriptorStream.WriteLine("[Session {0}]", i); Track firstSessionTrack = Tracks.FirstOrDefault(t => t.TrackSession == i); switch (firstSessionTrack?.TrackType) { case TrackType.Audio: // CloneCD always writes this value for first track in disc, however the Rainbow Books // say the first track pregap is no different from other session pregaps, same mode as // the track they belong to. _descriptorStream.WriteLine("PreGapMode=0"); break; case TrackType.Data: case TrackType.CdMode1: _descriptorStream.WriteLine("PreGapMode=1"); break; case TrackType.CdMode2Formless: case TrackType.CdMode2Form1: case TrackType.CdMode2Form2: _descriptorStream.WriteLine("PreGapMode=2"); break; default: throw new ArgumentOutOfRangeException(); } _descriptorStream.WriteLine("PreGapSubC=0"); } for (int i = 0; i < toc.TrackDescriptors.Length; i++) { long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec, toc.TrackDescriptors[i].Frame)); long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC, toc.TrackDescriptors[i].PFRAME)); if (alba > 405000) { alba = ((alba - 405000) + 300) * -1; } if (plba > 405000) { plba = ((plba - 405000) + 300) * -1; } _descriptorStream.WriteLine("[Entry {0}]", i); _descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber); _descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT); _descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR); _descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL); _descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO); _descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min); _descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec); _descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame); _descriptorStream.WriteLine("ALBA={0}", alba); _descriptorStream.WriteLine("Zero={0}", ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) + (toc.TrackDescriptors[i].PHOUR & 0x0F)); _descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN); _descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC); _descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME); _descriptorStream.WriteLine("PLBA={0}", plba); } _descriptorStream.Flush(); _descriptorStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }
/// <summary> /// Gets the track description /// </summary> /// <param name="trackId">track identifier</param> /// <returns>the track description</returns> public TrackDescription?GetTrackDescription(int trackId) { return(Tracks.FirstOrDefault(t => t.Id == trackId)); }
public Track GetTrackById(int trackId) => Tracks.FirstOrDefault(t => t.TrackId == trackId);
public bool Close() { if (!IsWriting) { ErrorMessage = "Image is not opened for writing"; return(false); } dataStream.Flush(); dataStream.Close(); subStream?.Flush(); subStream?.Close(); FullTOC.CDFullTOC?nullableToc = null; FullTOC.CDFullTOC toc; // Easy, just decode the real toc if (fulltoc != null) { nullableToc = FullTOC.Decode(fulltoc); } // Not easy, create a toc from scratch if (nullableToc == null) { toc = new FullTOC.CDFullTOC(); Dictionary <byte, byte> sessionEndingTrack = new Dictionary <byte, byte>(); toc.FirstCompleteSession = byte.MaxValue; toc.LastCompleteSession = byte.MinValue; List <FullTOC.TrackDataDescriptor> trackDescriptors = new List <FullTOC.TrackDataDescriptor>(); byte currentTrack = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { if (track.TrackSession < toc.FirstCompleteSession) { toc.FirstCompleteSession = (byte)track.TrackSession; } if (track.TrackSession <= toc.LastCompleteSession) { currentTrack = (byte)track.TrackSequence; continue; } if (toc.LastCompleteSession > 0) { sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack); } toc.LastCompleteSession = (byte)track.TrackSession; } byte currentSession = 0; foreach (Track track in Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) { trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); if (trackControl == 0 && track.TrackType != TrackType.Audio) { trackControl = (byte)CdFlags.DataTrack; } // Lead-Out if (track.TrackSession > currentSession && currentSession != 0) { (byte minute, byte second, byte frame)leadoutAmsf = LbaToMsf(track.TrackStartSector - 150); (byte minute, byte second, byte frame)leadoutPmsf = LbaToMsf(Tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last() .TrackStartSector); // Lead-out trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xB0, ADR = 5, CONTROL = 0, HOUR = 0, Min = leadoutAmsf.minute, Sec = leadoutAmsf.second, Frame = leadoutAmsf.frame, PHOUR = 2, PMIN = leadoutPmsf.minute, PSEC = leadoutPmsf.second, PFRAME = leadoutPmsf.frame }); // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC... trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xC0, ADR = 5, CONTROL = 0, Min = 128, PMIN = 97, PSEC = 25 }); } // Lead-in if (track.TrackSession > currentSession) { currentSession = (byte)track.TrackSession; sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber); (byte minute, byte second, byte frame)leadinPmsf = LbaToMsf(Tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber).TrackEndSector + 1); // Starting track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA0, ADR = 1, CONTROL = trackControl, PMIN = (byte)track.TrackSequence }); // Ending track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA1, ADR = 1, CONTROL = trackControl, PMIN = endingTrackNumber }); // Lead-out start trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = currentSession, POINT = 0xA2, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = leadinPmsf.minute, PSEC = leadinPmsf.second, PFRAME = leadinPmsf.frame }); } (byte minute, byte second, byte frame)pmsf = LbaToMsf(track.TrackStartSector); // Track trackDescriptors.Add(new FullTOC.TrackDataDescriptor { SessionNumber = (byte)track.TrackSession, POINT = (byte)track.TrackSequence, ADR = 1, CONTROL = trackControl, PHOUR = 0, PMIN = pmsf.minute, PSEC = pmsf.second, PFRAME = pmsf.frame }); } toc.TrackDescriptors = trackDescriptors.ToArray(); } else { toc = nullableToc.Value; } descriptorStream.WriteLine("[CloneCD]"); descriptorStream.WriteLine("Version=2"); descriptorStream.WriteLine("[Disc]"); descriptorStream.WriteLine("TocEntries={0}", toc.TrackDescriptors.Length); descriptorStream.WriteLine("Sessions={0}", toc.LastCompleteSession); descriptorStream.WriteLine("DataTracksScrambled=0"); descriptorStream.WriteLine("CDTextLength=0"); if (!string.IsNullOrEmpty(catalog)) { descriptorStream.WriteLine("CATALOG={0}", catalog); } for (int i = 1; i <= toc.LastCompleteSession; i++) { // TODO: Use first track of session info descriptorStream.WriteLine("[Session {0}]", i); descriptorStream.WriteLine("PreGapMode=0"); descriptorStream.WriteLine("PreGapSubC=0"); } for (int i = 0; i < toc.TrackDescriptors.Length; i++) { long alba = MsfToLba((toc.TrackDescriptors[i].Min, toc.TrackDescriptors[i].Sec, toc.TrackDescriptors[i].Frame)); long plba = MsfToLba((toc.TrackDescriptors[i].PMIN, toc.TrackDescriptors[i].PSEC, toc.TrackDescriptors[i].PFRAME)); if (alba > 405000) { alba = (alba - 405000 + 300) * -1; } if (plba > 405000) { plba = (plba - 405000 + 300) * -1; } descriptorStream.WriteLine("[Entry {0}]", i); descriptorStream.WriteLine("Session={0}", toc.TrackDescriptors[i].SessionNumber); descriptorStream.WriteLine("Point=0x{0:x2}", toc.TrackDescriptors[i].POINT); descriptorStream.WriteLine("ADR=0x{0:x2}", toc.TrackDescriptors[i].ADR); descriptorStream.WriteLine("Control=0x{0:x2}", toc.TrackDescriptors[i].CONTROL); descriptorStream.WriteLine("TrackNo={0}", toc.TrackDescriptors[i].TNO); descriptorStream.WriteLine("AMin={0}", toc.TrackDescriptors[i].Min); descriptorStream.WriteLine("ASec={0}", toc.TrackDescriptors[i].Sec); descriptorStream.WriteLine("AFrame={0}", toc.TrackDescriptors[i].Frame); descriptorStream.WriteLine("ALBA={0}", alba); descriptorStream.WriteLine("Zero={0}", ((toc.TrackDescriptors[i].HOUR & 0x0F) << 4) + (toc.TrackDescriptors[i].PHOUR & 0x0F)); descriptorStream.WriteLine("PMin={0}", toc.TrackDescriptors[i].PMIN); descriptorStream.WriteLine("PSec={0}", toc.TrackDescriptors[i].PSEC); descriptorStream.WriteLine("PFrame={0}", toc.TrackDescriptors[i].PFRAME); descriptorStream.WriteLine("PLBA={0}", plba); } descriptorStream.Flush(); descriptorStream.Close(); IsWriting = false; ErrorMessage = ""; return(true); }
protected override void OnPaint(PaintEventArgs e) { // Reset e.Graphics.Clear(bgColor); buttons.Clear(); int midx = Width / 2; // Richtungsangaben ermitteln var route = tt.GetRoute(routeIndex).Stations; var staIdx = route.IndexOf(station); var prev = route.ElementAtOrDefault(staIdx - 1); var next = route.ElementAtOrDefault(staIdx + 1); bool disableRight = tt.Type == TimetableType.Network && next == null; bool disableLeft = tt.Type == TimetableType.Network && prev == null; // Richtungsangaben zeichnen if (prev != null) { e.Graphics.DrawText(font, textColor, 5, 5, T._("von {0}", prev.SName)); } if (next != null) { var nextText = T._("nach {0}", next.SName); var nextSize = e.Graphics.MeasureString(font, nextText); e.Graphics.DrawText(font, textColor, Width - 5 - nextSize.Width, 5, nextText); } var leftdefaultTrack = Tracks.IndexOf(Tracks.FirstOrDefault(t => t.Name == DefaultTrackLeft.GetValue(routeIndex))); var rightdefaultTrack = Tracks.IndexOf(Tracks.FirstOrDefault(t => t.Name == DefaultTrackRight.GetValue(routeIndex))); // Netzwerk: Falls noch keine Angabe: Standardgleise setzen if (tt.Type == TimetableType.Network && Tracks.Any()) { if (disableLeft) { leftdefaultTrack = 0; } else if (leftdefaultTrack == -1) { MoveDefaultTrack(DefaultTrackLeft, Tracks.First(), 0); leftdefaultTrack = 0; } if (disableRight) { rightdefaultTrack = 0; } else if (rightdefaultTrack == -1) { MoveDefaultTrack(DefaultTrackRight, Tracks.First(), 0); rightdefaultTrack = 0; } } int y = 30; int maxIndent = 0; foreach (var track in Tracks) { var trackIndex = Tracks.IndexOf(track); // Einrückung des Gleisvorfeldes berehcnen var leftIndent = Math.Abs(leftdefaultTrack - trackIndex) * INDENT + 60; if (leftdefaultTrack == trackIndex) { leftIndent = disableLeft ? 30 : 0; } var rightIndent = Math.Abs(rightdefaultTrack - trackIndex) * INDENT + 60; if (rightdefaultTrack == trackIndex) { rightIndent = disableRight ? 30 : 0; } maxIndent = Math.Max(maxIndent, rightIndent + leftIndent); rightIndent = Width - rightIndent; // Gleiselinie zeichnen e.Graphics.DrawLine(textColor, leftIndent, y, rightIndent, y); // Gleisverbindungen zeichnen if (trackIndex < leftdefaultTrack) { e.Graphics.DrawLine(textColor, leftIndent, y, leftIndent - INDENT, y + LINE_HEIGHT); } else if (trackIndex > leftdefaultTrack) { e.Graphics.DrawLine(textColor, leftIndent, y, leftIndent - INDENT, y - LINE_HEIGHT); } if (trackIndex < rightdefaultTrack) { e.Graphics.DrawLine(textColor, rightIndent, y, rightIndent + INDENT, y + LINE_HEIGHT); } else if (trackIndex > rightdefaultTrack) { e.Graphics.DrawLine(textColor, rightIndent, y, rightIndent + INDENT, y - LINE_HEIGHT); } // Gleisnamen als Button hinzufügen var textSize = e.Graphics.MeasureString(font, track.Name); var nameBtn = new RenderBtn <Track>(track, new Point(midx - (int)(textSize.Width / 2) - 5, y - 8), new Size((int)textSize.Width + 5, 16), bgColor, track.Name, textColor); nameBtn.Click += NameBtn_Click; buttons.Add(nameBtn); // Netzwerk: Standardgleise anderer Routen gestrichelt zeichnen. if (DefaultTrackLeft.ContainsValue(track.Name) && leftdefaultTrack != trackIndex) { e.Graphics.DrawLine(dashedPen, 0, y, leftIndent, y); } if (DefaultTrackRight.ContainsValue(track.Name) && rightdefaultTrack != trackIndex) { e.Graphics.DrawLine(dashedPen, rightIndent, y, Width, y); } // Aktions-Buttons hinzufügen var btnLeft = midx + (int)(textSize.Width / 2) + 10; var deleteBtn = GetButton("X", track, btnLeft, y); deleteBtn.Click += DeleteBtn_Click; var upBtn = GetButton("▲", track, btnLeft + 20, y); upBtn.Click += UpBtn_Click; var downBtn = GetButton("▼", track, btnLeft + 40, y); downBtn.Click += DownBtn_Click; // Aktionsbuttons für Standardgleise if (trackIndex == leftdefaultTrack && !disableLeft) { var leftUpBtn = GetButton("▲", track, 10, y); leftUpBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackLeft, ((RenderBtn <Track>)s).Tag, -1); var leftDownBtn = GetButton("▼", track, 30, y); leftDownBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackLeft, ((RenderBtn <Track>)s).Tag, 1); } if (trackIndex == rightdefaultTrack && !disableRight) { var rightUpButton = GetButton("▲", track, Width - 46, y); rightUpButton.Click += (s, x) => MoveDefaultTrack(DefaultTrackRight, ((RenderBtn <Track>)s).Tag, -1); var rightDownBtn = GetButton("▼", track, Width - 26, y); rightDownBtn.Click += (s, x) => MoveDefaultTrack(DefaultTrackRight, ((RenderBtn <Track>)s).Tag, 1); } y += LINE_HEIGHT; } // Button für neue Gleise var addTrackText = T._("Neues Gleis hinzufügen"); var textWidth = (int)e.Graphics.MeasureString(font, addTrackText).Width; var addBtn = new RenderBtn <Track>(null, new Point(midx - (textWidth / 2) - 5, y - 8), new Size(textWidth + 10, 16), Colors.LightGrey, addTrackText); buttons.Add(addBtn); addBtn.Click += AddBtn_Click; var newHeight = (Tracks.Count) * LINE_HEIGHT + 50; if (newHeight > Height) { this.Height = newHeight; } else if (maxIndent > Width - 30) { Width = maxIndent + 30; } foreach (var args in buttons) { args.Draw(e.Graphics); } base.OnPaint(e); }