Problems with Markers

Topics: Developer Forum
May 16, 2009 at 11:03 AM

I have a little Marker sample:

 

namespace MarkerDemo
{
  class MarkerDemo : System.Windows.Forms.Form
  {
  private ScintillaNet.Scintilla _scintilla;
  private ScintillaNet.Marker _markerF2 = null;

  private MarkerDemo()
  {
  this.Size = new System.Drawing.Size(500, 500);
  _scintilla = new ScintillaNet.Scintilla();
  _scintilla.Parent = this;
  _scintilla.Dock = System.Windows.Forms.DockStyle.Fill;
  _scintilla.Margins[0].Width = 20; // place for line numbers
  _scintilla.Margins[1].Width = 20; // place for markers
  _scintilla.Margins[2].Width = 20; // place for folding symbols (not used in this sample)
  // filling with some dummy text
  System.Text.StringBuilder sb = new System.Text.StringBuilder(200);
  bool first = true;
  for (int lineNo = 0; lineNo < 20; ++lineNo)
  {
  if (first)
  first = false;
  else
  sb.Append("\n");
  sb.Append("line ").Append(lineNo);
  }
  _scintilla.Text = sb.ToString();
  _scintilla.KeyUp += new System.Windows.Forms.KeyEventHandler(scintilla1_KeyUpF2);
  _markerF2 = _scintilla.Markers[2]; // No2 is just a sample
  _markerF2.BackColor = System.Drawing.Color.AliceBlue; // the ultraedit style
  _markerF2.Symbol = ScintillaNet.MarkerSymbol.RoundRectangle; // the ultraedit style
  }

  // use markers with F2, just like UltraEdit does!
  private void scintilla1_KeyUpF2(object sender, System.Windows.Forms.KeyEventArgs e)
  {
  if (e.KeyCode != System.Windows.Forms.Keys.F2)
  return;
  ScintillaNet.Line currentLine = _scintilla.Lines.Current;
  if (e.Control)
  {
  // the GetMarkers will retrieve the wrong markers
  // independently the Contains method will always fail
  if (currentLine.GetMarkers().Contains(_markerF2))
  currentLine.DeleteMarker(_markerF2.Number); // there is only this signature
  else
  currentLine.AddMarker(_markerF2);
  return;
  }
  ScintillaNet.Line found = null;
  if (e.Shift)
  found = currentLine.FindPreviousMarker(_markerF2);
  else
  found = currentLine.FindNextMarker(_markerF2);
  // found will always be null!
  if (found != null)
  found.Goto();
  }

  [System.STAThread]
  static void Main()
  {
  System.Windows.Forms.Application.Run(new MarkerDemo());
  }
  }
}

This sample doesn't work, because there are some problems in the Marker and Line classes.

To make it work, I had to change the source:

 public class Marker : ScintillaHelperBase
 {
  // fxa added

//  because Line.GetMarkers returns new instances, you must be able to compare different instances
  public override bool Equals(object obj)
  {
  Marker other = obj as Marker;
  if (other == null)
  return false;
  if (!base.Equals(obj))
  return false;
  return Number == other.Number;
  }


  // fxa added

// the native interface likes the binary mask for the 32 markers, so we have to shift some bits around
  internal uint Mask
  {
  get
  {
  uint result = ((uint)1) << Number;
  return result;
  }
  }
...

}

 

corrected in Lines.cs:

  // fxa reimplemented.
  // the native interface returns not the marker number, but the bit mask
  //public List<Marker> GetMarkers()
  //{
  // List<Marker> ret = new List<Marker>();
  // int mask = GetMarkerMask();
  // for (int i = 0; i < 32; i++)
  // if ((mask & i) == i)
  // ret.Add(new Marker(Scintilla, i));

  // return ret;
  //}
  public List<Marker> GetMarkers()
  {
  List<Marker> ret = new List<Marker>();
  int mask = GetMarkerMask();
  int bit = 1;
  for (int i = 0; i < 32; ++i)
  {
  if ((mask & bit) != 0)
  ret.Add(new Marker(Scintilla, i));
  bit = bit + bit;
  }

  return ret;
  }

  // fxa reimplemented
  // the native interface needs the mask
  //public Line FindNextMarker(Marker marker)
  //{
  // return FindNextMarker((uint)marker.Number);
  //}
  public Line FindNextMarker(Marker marker)
  {
  return FindNextMarker(marker.Mask);
  }

  // fxa reimplemented
  //public Line FindPreviousMarker(Marker marker)
  //{
  // return FindPreviousMarker((uint)marker.Number);
  //}
  public Line FindPreviousMarker(Marker marker)
  {
  return FindPreviousMarker( marker.Mask);
  }

  // fxa obsoleted
  [Obsolete("use DeleteMarker(Marker) instead")]
  public void DeleteMarker(int markerNumber)
  {
  NativeScintilla.MarkerDelete(_number, markerNumber);
  }

  // fxa added
  public void DeleteMarker(Marker marker )
  {
  NativeScintilla.MarkerDelete(_number, marker.Number);
  }

in ScintillaHelperBase.cs:

  // fxa added
  public override bool Equals(object obj)
  {
  ScintillaHelperBase other = obj as ScintillaHelperBase;
  if (other == null)
  return false;
  return this._scintilla.Equals(other._scintilla);
  }

and finnaly in Utils.cs

  // fxa corrected
  //public static uint GetMarkerMask(IEnumerable<int> markers)
  //{
  // uint mask = 0;
  // foreach (int i in markers)
  // mask |= (uint)i;
  // return mask;
  //}
  public static uint GetMarkerMask(IEnumerable<int> markers)
  {
  uint mask = 0;
  foreach (int i in markers)
  mask |= ((uint)1) << i;
  return mask;
  }

  // fxa corrected
  //public static uint GetMarkerMask(IEnumerable<Marker> markers)
  //{
  // uint mask = 0;
  // foreach (Marker m in markers)
  // mask |= (uint)m.Number;
  // return mask;
  //}
  public static uint GetMarkerMask(IEnumerable<Marker> markers)
  {
  uint mask = 0;
  foreach (Marker m in markers)
  mask |= m.Mask;
  return mask;
  }

The aim should be to work completely with the new Marker classes  without the native interface and without the

mask/number properties. In the sample above, there is only one line containing the marker number. I like that code ;-)
 I even think, it would be better to remove a lot of methods from the Marker and Line class. The user should not be

bothered with those bit shiftings. And when he likes to, he can use the native interface

 

 

Coordinator
Oct 14, 2009 at 9:32 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.