Side of Software

 

 

Home

 

Contact Us

 

 

 Products

 

Dated Collections

 

Marker Bar

 

FAQs

 

Features

Tutorial

 

API (javadocs)

 

Persistence

 

Print Preview

 

Reports

 

Wizards

Marker Bar Library Tutorial

Table of Contents

Introduction

JMarkerBar

Defining Markers

Providing a Marker Action

Customizing the Markers

Introduction

A marker bar is a stripe, typically next to a scroll bar, that visually indicates where objects fall in a document. Each visual indication along the bar is called a marker, because it marks a place in the document. If the document is long, a marker tells the user where he or she needs to scroll in order to see a particular object. Popular applications such as Visual Studio, Eclipse, NetBeans, and MATLAB all use a marker bar to visually indicate where compiler errors and breakpoints fall in a file. Here is a screen shot of a marker bar within NetBeans.

 

NetBeans screen shot showing its error stripe

Although the above screen shot shows markers for compiler errors, source code suggestions, and the current cursor position, the possible uses for markers are endless. Markers can also represent search matches, bookmarks, headings, file differences, and anything else conceivably found in a document.

JMarkerBar

The Marker Bar Library contains a Java Swing component, JMarkerBar, that draws a marker bar. JMarkerBar can be laid out vertically or horizontally depending on its orientation property. You can set its orientation to JMarkerBar.Y_AXIS to force the marker bar to be laid out vertically or to JMarkerBar.X_AXIS to get a horizontal bar. Alternatively, the constants JMarkerBar.PAGE_AXIS and JMarkerBar.LINE_AXIS will use the locale to determine the direction. The default orientation is PAGE_AXIS.

 

In the United States locale, the following code snippet creates a vertical JMarkerBar and adds it to the right of a scroll pane.


  JMarkerBar markerBar = new JMarkerBar();
  markerBar.setOrientation( JMarkerBar.PAGE_AXIS );
  panel.add( scrollPane, BorderLayout.CENTER );
  panel.add( markerBar, BorderLayout.LINE_END );
  

Defining Markers

You can think of a marker bar as a range from 0.0 to 1.0, where 0.0 represents the start of the bar and 1.0 represents the end. Then each marker defines a range within the marker bar's range. For example, a marker may define the range [0.32,0.62], as in the following illustrations.

 

Illustrations of a marker positioned on a vertical and horizontal marker bar

The Marker interface encapsulates the concept of a marker and is defined as


  public interface Marker
  {
    public double getStart();
    public double getEnd();
    publid double getShortDescription();
  }
  

The getStart method returns the marker's starting percentage along the marker bar, while getEnd returns the end percentage. The method getShortDescription allows you to give a marker a textual description, which is used as the marker's tooltip by the default renderer. You may define your own implementations of the Marker interface or use the pre-defined DefaultMarker class.

 

A JMarkerBar contains a list of Marker objects. Instead of defining a new type of model for a JMarkerBar, the library uses the well-known javax.swing.ListModel to supply the markers. You can pass the list of markers to JMarkerBar's constructor or set it with a call to setModel. Even though the ListModel interface allows elements of any type, the list model given to the JMarkerBar must return elements that implement the Marker interface. The contents of the list model are allowed to change dynamically, and the marker bar redraws itself accordingly. The markers are drawn in the order returned by the list model. Since markers may be drawn on top of each other, it is your responsibility to return the correct order and to coordinate overlapping markers, if necessary.

 

The following code creates a marker bar with a hard-coded marker.


  DefaultListModel markerModel = new DefaultListModel();
  markerModel.addElement( new DefaultMarker( 0.12, 0.15 ));
  JMarkerBar markerBar = new JMarkerBar( markerModel );
  

The marker range in the above example is arbitrary and used stricly as an example. Ranges typically correspond to locations within a text component, list, or table. Therefore, the library provides static Utility methods to aid in converting component indices into markers.


  public static double[] listIndexToMarkerRange( JList list, int row );
  public static double[] listRangeToMarkerRange( JList list, int startIndex, int endIndex );
  public static double[] textIndexToMarkerRange( JTextComponent textComponent, int index );
  public static double[] textRangeToMarkerRange( JTextComponent textComponent, int startIndex, int endIndex );
  public static double[] tableIndexToMarkerRange( JTable table, int row, int column );
  public static double[] tableRangeToMarkerRange( JTable table, int startRow, int startColumn, int endRow, int endColumn );
  

The following code uses one of these Utility methods to acquire a more meaningful marker range.


  DefaultListModel markerModel = new DefaultListModel();
  double[] markerRange = Utility.textRangeToMarkerRange( textPane, 12, 19 );
  markerModel.addElement( new DefaultMarker( markerRange[0], markerRange[1] ));
  JMarkerBar markerBar = new JMarkerBar( markerModel );
  

Providing a Marker Action

A user can "activate" a marker by clicking on it in the marker bar. An action event is then sent to all registered listeners of the marker bar. You can register an action listener invoking addActionListener, as is done in the following code


  markerBar.addActionListener( new ActionListener() {
    public void actionPerformed( ActionEvent event )
    {
      int markerIndex = markerBar.getClickedIndex();
      Utility.scrollToMarker( componentToScroll, markerBar, markerIndex );
    }
  } );
  

Listeners can determine the marker that was clicked by calling getClickedIndex on the JMarkerBar. The marker index can then be used to fetch the marker in the list model if needed. Since a common action is to jump to the location marked by the marker, the Utility class provides some helpful methods for scrolling.


  public static void scrollHorizontallyToMarker( JComponent componentToScroll, Marker marker );
  public static void scrollVerticallyToMarker( JComponent componentToScroll, Marker marker );
  public static void scrollToMarker( JComponent componentToScroll, JMarkerBar markerBar, int markerIndex );
  

Customizing the Markers

Just like javax.swing.JTable and javax.swing.JList do, JMarkerBar uses a renderer to draw the individual markers. The default renderer--an instance of DefaultMarkerRenderer--draws a marker as a rectangle using the JMarkerBar's foreground color. You can change the color either by changing the marker bar's foreground or by calling setColor on the DefaultMarkerRenderer, as in the following example.


  DefaultMarkerRenderer markerRenderer = new DefaultMarkerRenderer();
  markerRenderer.setColor( Color.GREEN );
  markerRenderer.setBorder( BorderFactory.createLineBorder( Color.BLACK ));
  markerRenderer.setMinimumSize( new Dimension( Integer.MAX_VALUE, 3 ));
  markerRenderer.setPreferredSize( new Dimension( Integer.MAX_VALUE, 3 ));
  markerRenderer.setAlignmentY( 0.0 );
  markerBar.setMarkerRenderer( markerRenderer );
  

By default, the rectangle will be drawn the full width of the bar and the full height corresponding to the marker's range. You can adjust the dimensions of the rectangle by setting the DefaultMarkerRenderer's preferred and minimum sizes. The above example wishes each marker to occupy the full width of the marker bar and to be exactly 3 pixels high. If the region given to a renderer is smaller than the full marker's region, then the marker bar uses the renderer's X and Y alignments to position the marker horizontally and vertically. The above example sets the Y alignment to 0.0, meaning that the rectangle should be positioned at the top of the marker's region.

 

If DefaultMarkerRenderer does not meet your needs, you can either subclass it or define a new implementation of MarkerRenderer. The following MarkerRenderer implementation assumes there are different types of markers and uses a different renderer for each type:


  public class CustomMarkerRenderer implements MarkerRenderer
  {
    private static final MarkerRenderer SEARCH_RENDERER = ...
    private static final MarkerRenderer COMPILER_RENDERER = ...
    private static final MarkerRenderer DIFF_RENDERER = ...
    private static final MarkerRenderer CURSOR_RENDERER = ...
    private static final MarkerRenderer DEFAULT_RENDERER = ...

    public Component getMarkerRendererComponent( JMarkerBar markerBar, int markerIndex, Marker marker )
    {
      if( marker instanceof SearchMarker )
        return SEARCH_RENDERER;
      else if( marker instanceof CompilerMarker )
        return COMPILER_RENDERER;
      else if( marker instanceof DiffMarker )
        return DIFF_RENDERER;
      else if( marker instanceof CursorMarker )
        return CURSOR_MARKER;
      else
        return DEFAULT_MARKER;
    }
  }
  

Such a renderer allows you to build sophisticated marker bars with a mix of colors, styles, borders, shapes, and sizes.

 

 

 

Home  |  Contact Us  |  Privacy Policy

 

Copyright 2016 Side of Software, a branch of Natavision. All rights reserved.