Processing Java - how to make slider proportional to contents of file

I have modified Processing's example Scrollbar/Slider class to be oriented vertically and have the slider start on top instead of the middle. The ratio of the slider's length to the scrollbar is the ratio of the maximum number of lines the text area can hold to the number of lines in the file. The scrollbar works perfectly in terms of moving the text along but their is one slight problem:

Upon opening relatively large files, the scrollbar goes too far, as in when the scrollbar reaches the end, the end of the document should be reached. However the scrollbar goes farther, with extra blank lines. The positioning of the text box could be off because I transferred the code from the text editor I am making.

The file I tested was 554 lines in length.

Here is the main file:

Scrollbar bar;
String content = "";
float scrollbarRatio;
String absolutePath;
int line;

void setup()
{
  // Background and size
  background(0);
  size(int(displayWidth * 4/5), int(displayHeight * 4/5));

  // Resizable Window
  if (frame != null) {
    frame.setResizable(true);
  }

  // Scrollbar
  bar = new Scrollbar(width-12, 55, 24, height - 79, 1);

  // Input
  selectInput("Select a file to process:", "openFile");
}

// Create set of line numbers given starting number and number of lines
void createLineNumbers(int startingNumber, int numberOfLines)
{
  textAlign(LEFT);
  String lineText = "";
  textLeading(22);

  for (int i = startingNumber; i <= startingNumber + numberOfLines; i++)
  {
    lineText += (str(i) + "\n");
  }

  text(lineText, width/5 + 12.5, 75);
  textAlign(CENTER);
}

void draw()
{
  String[] adjustedLines = content.split("\n");

  int maxLines = floor((height - 80) / 22);

  if (adjustedLines.length > maxLines)
  {
    scrollbarRatio = ((float) maxLines) / ((float) adjustedLines.length);
  }

  // Text Box
  fill(80);
  rect(width/5, 55, width*4/5, height-55);

  textAlign(LEFT);
  textLeading(22);
  fill(225);

  String[] contentLines = content.split("\n");
  String display = "";

  int lineDifference = bar.getLineDifference();

  if (adjustedLines.length > maxLines)
  {
    for (int i = lineDifference; i < maxLines + lineDifference; i++)
    {
      if (i < adjustedLines.length)
      {
        display += adjustedLines[i];
        display += "\n";
      }
    }
  } else
  {
    display = content;
  }

  text(display, width/5+55, 75);

  fill(240);

  if (maxLines < adjustedLines.length)
  {
    createLineNumbers(lineDifference, lineDifference + maxLines);
  } else if (maxLines >= adjustedLines.length)
  {
    createLineNumbers(1, adjustedLines.length);
  }

  bar.resizeScrollbar(width-12, 55, 24, height - 79);
  bar.update(scrollbarRatio);
  bar.display(scrollbarRatio);
}

// File - Open
void openFile(File selection)
{
  if (selection != null)
  {
    try
    {
      // Read content of file
      absolutePath = selection.getAbsolutePath();
      String lines[] = loadStrings(absolutePath);

      // Reset content and line numbers
      content = "";
      line = 0;

      for (int i = 0; i < lines.length; i++) {
        String lineContent = lines[i] + "\n";
        content += lineContent;
        line++;
      }
    }
    catch (Exception exc)
    {
      println(exc.getMessage());
    }
  }
}

And here is the Scrollbar class:

class Scrollbar
{
  float swidth, sheight;    // width and height of bar
  float xpos, ypos;         // x and y position of bar
  float spos, newspos;      // x position of slider
  float sposMin, sposMax;   // max and min values of slider
  int loose;                // how loose/heavy
  boolean over;             // is the mouse over the slider?
  boolean locked;           // is the mouse clicked over the slider
  int lineDifference;       

  Scrollbar (int xp, int yp, int sw, int sh, int l) {
    swidth = sw;
    sheight = sh;
    xpos = xp-swidth/2;
    ypos = yp;
    spos = ypos;
    newspos = spos;
    sposMin = ypos;
    sposMax = ypos + sheight;
    loose = l;
  }

  void resizeScrollbar(int xp, int yp, int sw, int sh)
  {
    xpos = xp - swidth/2;
    ypos = yp;
    swidth = sw;
    sheight = sh;
  }

  void update(float ratio) {
    if (over()) {
      over = true;
    } else {
      over = false;
    }
    if (mousePressed && over) {
      locked = true;
    }
    if (!mousePressed) {
      locked = false;
    }
    if (locked) {
      sposMax = ypos + sheight;
      newspos = constrain(mouseY-swidth/2, sposMin, sposMax - sheight * ratio);
      lineDifference = ceil((newspos - 55)/22 * (1/ratio));

      if (abs(newspos - spos) > 1) {
        spos = spos + (newspos-spos)/loose;
      }
    }
  }

  float constrain(float val, float minv, float maxv) {
    return min(max(val, minv), maxv);
  }

  boolean over() {
    if (mouseX > xpos && mouseX < xpos+swidth &&
      mouseY > ypos && mouseY < ypos+sheight) {
      return true;
    } else {
      return false;
    }
  }

  void display(float ratio) {
    fill(220);
    rect(xpos, ypos, swidth, sheight);

    if (over || locked) {
      fill(80);
    } else {
      fill(190);
    }

    // Removes whitespace between slider and beginning of scrollbar
    if (spos != 55 && floor(spos) == 55)
    {
      spos = 55;
    }

    // Removes whitespace between slider and end of scrollbar
    if ((spos + sheight * ratio) != (sheight + ypos) && ceil(spos + sheight * ratio) == (sheight + ypos))
    {
      spos = sheight + ypos - (sheight * ratio);
    }

    rect(xpos, spos, swidth, sheight * ratio);
  }

  int getLineDifference()
  {
    return lineDifference;
  }
}
Tagged:

Answers

Sign In or Register to comment.