Package timeflow.vis.timeline

Source Code of timeflow.vis.timeline.TimelineSlider

package timeflow.vis.timeline;

import timeflow.data.db.*;
import timeflow.data.time.*;
import timeflow.model.*;
import timeflow.vis.TimeScale;
import timeflow.vis.VisualAct;
import timeflow.vis.timeline.*;

import timeflow.util.*;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

public class TimelineSlider extends ModelPanel {
 
  TimelineVisuals visuals;
  Interval original;
  long minRange;
  int ew=10;
  int eventRadius=2;
  TimeScale scale;
 
  Point mouseHit=new Point();
  Point mouse=new Point(-1,0);
  enum Modify {START, END, POSITION, NONE};
  Modify change=Modify.NONE;
  Rectangle startRect=new Rectangle(-1,-1,0,0);
  Rectangle endRect=new Rectangle(-1,-1,0,0);
  Rectangle positionRect=new Rectangle(-1,-1,0,0);
  Color sidePlain=Color.orange;
  Color sideMouse=new Color(230,100,0);

 
  public TimelineSlider(final TimelineVisuals visuals, final long minRange, final Runnable action)
  {
    super(visuals.getModel());
   
    this.minRange=minRange;
    this.visuals=visuals;
   
    addMouseListener(new MouseAdapter() {

      @Override
      public void mousePressed(MouseEvent e) {
        int mx=e.getX();
        int my=e.getY();
        if (positionRect.contains(mx,my))
          change=Modify.POSITION;
        else if (startRect.contains(mx, my))
          change=Modify.START;
        else if (endRect.contains(mx,my))
          change=Modify.END;
        else
          change=Modify.NONE;
        mouseHit.setLocation(mx,my);
        original=window().copy();
        mouse.setLocation(mx,my);
        repaint();
      }

      @Override
      public void mouseReleased(MouseEvent e) {
        change=Modify.NONE;
        repaint();
      }});
    addMouseMotionListener(new MouseMotionAdapter() {

      @Override
      public void mouseDragged(MouseEvent e) {
       
        if (change==Modify.NONE)
          return;
        mouse.setLocation(e.getX(), e.getY());
        int mouseDiff=mouse.x-mouseHit.x;
        Interval limits=visuals.getGlobalInterval();
        long timeDiff=scale.spaceToTime(mouseDiff);
       
        switch (change)
        {
          case POSITION:            
              window().translateTo(original.start+timeDiff);
              window().clampInside(limits);
            break;
          case START: window().start=Math.min(original.start+timeDiff, original.end-minRange);
                window().start=Math.max(window().start, limits.start);
            break;
          case END: window().end=Math.max(original.end+timeDiff, original.start+minRange);
                window().end=Math.min(window().end, limits.end);
        }
        getModel().setViewInterval(window());
        action.run();
        repaint();
      }
    });
  }
 
  private Interval window()
  {
    return visuals.getViewInterval();
  }
 
  @Override
  public Dimension getPreferredSize()
  {
    return new Dimension(600,30);
  }
 
  public void setMinRange(long minRange)
  {
    this.minRange=minRange;
  }

  @Override
  public void note(TFEvent e) {
    repaint();
  }
 
  void setTimeInterval(Interval interval)
  {
    window().setTo(interval);
    repaint();
  }
 
  public void paintComponent(Graphics g1)
  {
    int w=getSize().width, h=getSize().height;
    Graphics2D g=(Graphics2D)g1;
   
    long start=System.currentTimeMillis();
   
    // draw main backdrop.
    g.setColor(Color.white);
    g.fillRect(0,0,w,h);
   
    if (visuals.getModel()==null || visuals.getModel().getActs()==null)
    {
      g.setColor(Color.darkGray);
      g.drawString("No data for timeline.", 5, 20);
      return;
    }
   
    scale=new TimeScale();
    scale.setDateRange(visuals.getGlobalInterval());
    scale.setNumberRange(ew, w-ew);
   
   
    // draw the area for the central "thumb".
    int lx=scale.toInt(window().start);
    int rx=scale.toInt(window().end);
    g.setColor(change==Modify.POSITION ? new Color(255,255,120) : new Color(255,245,200));
    positionRect.setBounds(lx,0,rx-lx,h);
    g.fill(positionRect);   

    // Figure out how best to draw events.
    // If there are too many, we just draw a kind of histogram of frequency,
    // rather than using the timeline layout.
    int slotW=2*eventRadius;
    int slotNum=w/slotW+1;
    int[] slots=new int[slotNum];
    int mostInSlot=0;
    for (VisualAct v: visuals.getVisualActs())
    {
      if (!v.isVisible())
        continue;
      int x=scale.toInt(v.getStart().getTime());
      int s=x/slotW;
      if (s>=0 && s<slotNum)
      {
        slots[s]++;
        mostInSlot=Math.max(mostInSlot, slots[s]);
      }
    }
    if (mostInSlot>30)
    {
      g.setColor(Color.gray);
      for (int i=0; i<slots.length; i++)
      {
        int sh=(h*slots[i])/mostInSlot;
        g.fillRect(slotW*i, h-sh, slotW, sh);
      }
    }
    else
    {
      // draw individual events.
      for (VisualAct v: visuals.getVisualActs())
      {
        if (!v.isVisible())
          continue;
        g.setColor(v.getColor());
        int x=scale.toInt(v.getStart().getTime());
 
        int y=eventRadius+(int)(v.getY()*h)/(visuals.getBounds().height-2*eventRadius);
        g.fillRect(x-1,y-eventRadius,2*eventRadius,3);
        if (v.getEnd()!=null)
        {
          int endX=scale.toInt(v.getEnd().getTime());
          g.drawLine(x,y,endX,y);
        }
      }
    }
   
    g.setColor(Color.gray);
    g.drawLine(0,0,w,0);
    g.drawLine(0,h-1,w,h-1);
   
    // draw "expansion" areas on sides of thumb.
    startRect.setBounds(positionRect.x-ew,1,ew,h-2);
    g.setColor(change==Modify.START ? sideMouse : sidePlain);
    g.fill(startRect);
    endRect.setBounds(positionRect.x+positionRect.width,1,ew,h-2);
    g.setColor(change==Modify.END ? sideMouse : sidePlain);
    g.fill(endRect);
  }
}
TOP

Related Classes of timeflow.vis.timeline.TimelineSlider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.