/[classpath]/classpath/javax/swing/text/PlainView.java
ViewVC logotype

Diff of /classpath/javax/swing/text/PlainView.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1.2.9 by gnu_andrew, Tue Sep 20 18:46:35 2005 UTC revision 1.1.2.10 by gnu_andrew, Wed Nov 2 00:44:03 2005 UTC
# Line 46  import java.awt.Graphics; Line 46  import java.awt.Graphics;
46  import java.awt.Rectangle;  import java.awt.Rectangle;
47  import java.awt.Shape;  import java.awt.Shape;
48    
49  public class PlainView extends View  import javax.swing.event.DocumentEvent;
50    implements TabExpander  import javax.swing.event.DocumentEvent.ElementChange;
51    
52    public class PlainView extends View implements TabExpander
53  {  {
54    Color selectedColor;    Color selectedColor;
55    Color unselectedColor;    Color unselectedColor;
# Line 59  public class PlainView extends View Line 61  public class PlainView extends View
61    
62    Font font;    Font font;
63        
64      /** The length of the longest line in the Document **/
65      float maxLineLength = -1;
66      
67      /** The longest line in the Document **/
68      Element longestLine = null;
69      
70    protected FontMetrics metrics;    protected FontMetrics metrics;
71    
72      /**
73       * The instance returned by {@link #getLineBuffer()}.
74       */
75      private transient Segment lineBuffer;
76    
77    public PlainView(Element elem)    public PlainView(Element elem)
78    {    {
79      super(elem);      super(elem);
# Line 110  public class PlainView extends View Line 123  public class PlainView extends View
123      // Get the rectangle for position.      // Get the rectangle for position.
124      Element line = getElement().getElement(lineIndex);      Element line = getElement().getElement(lineIndex);
125      int lineStart = line.getStartOffset();      int lineStart = line.getStartOffset();
126      Segment segment = new Segment();      Segment segment = getLineBuffer();
127      document.getText(lineStart, position - lineStart, segment);      document.getText(lineStart, position - lineStart, segment);
128      int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,      int xoffset = Utilities.getTabbedTextWidth(segment, metrics, rect.x,
129                                                 this, lineStart);                                                 this, lineStart);
# Line 135  public class PlainView extends View Line 148  public class PlainView extends View
148        }        }
149      catch (BadLocationException e)      catch (BadLocationException e)
150        {        {
151          // This should never happen.          AssertionError ae = new AssertionError("Unexpected bad location");
152            ae.initCause(e);
153            throw ae;
154        }        }
155    }    }
156    
# Line 143  public class PlainView extends View Line 158  public class PlainView extends View
158      throws BadLocationException      throws BadLocationException
159    {    {
160      g.setColor(selectedColor);      g.setColor(selectedColor);
161      Segment segment = new Segment();      Segment segment = getLineBuffer();
162      getDocument().getText(p0, p1 - p0, segment);      getDocument().getText(p0, p1 - p0, segment);
163      return Utilities.drawTabbedText(segment, x, y, g, this, 0);      return Utilities.drawTabbedText(segment, x, y, g, this, 0);
164    }    }
# Line 157  public class PlainView extends View Line 172  public class PlainView extends View
172      else      else
173        g.setColor(disabledColor);        g.setColor(disabledColor);
174    
175      Segment segment = new Segment();      Segment segment = getLineBuffer();
176      getDocument().getText(p0, p1 - p0, segment);      getDocument().getText(p0, p1 - p0, segment);
177      return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);      return Utilities.drawTabbedText(segment, x, y, g, this, segment.offset);
178    }    }
# Line 188  public class PlainView extends View Line 203  public class PlainView extends View
203        }        }
204    }    }
205    
206      /**
207       * Returns the tab size of a tab.  Checks the Document's
208       * properties for PlainDocument.tabSizeAttribute and returns it if it is
209       * defined, otherwise returns 8.
210       *
211       * @return the tab size.
212       */
213    protected int getTabSize()    protected int getTabSize()
214    {    {
215      return 8;      Object tabSize = getDocument().getProperty(PlainDocument.tabSizeAttribute);
216        if (tabSize == null)
217          return 8;
218        return ((Integer)tabSize).intValue();
219    }    }
220    
221    /**    /**
# Line 203  public class PlainView extends View Line 228  public class PlainView extends View
228     */     */
229    public float nextTabStop(float x, int tabStop)    public float nextTabStop(float x, int tabStop)
230    {    {
231      float tabSizePixels = getTabSize() + metrics.charWidth('m');      float tabSizePixels = getTabSize() * metrics.charWidth('m');
232      return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;      return (float) (Math.floor(x / tabSizePixels) + 1) * tabSizePixels;
233    }    }
234    
235      /**
236       * Returns the length of the longest line, used for getting the span
237       * @return the length of the longest line
238       */
239      float determineMaxLineLength()
240      {
241        // if the longest line is cached, return the cached value
242        if (maxLineLength != -1)
243          return maxLineLength;
244        
245        // otherwise we have to go through all the lines and find it
246        Element el = getElement();
247        Segment seg = getLineBuffer();
248        float span = 0;
249        for (int i = 0; i < el.getElementCount(); i++)
250          {
251            Element child = el.getElement(i);
252            int start = child.getStartOffset();
253            int end = child.getEndOffset();
254            try
255              {
256                el.getDocument().getText(start, end - start, seg);
257              }
258            catch (BadLocationException ex)
259              {
260                AssertionError ae = new AssertionError("Unexpected bad location");
261                ae.initCause(ex);
262                throw ae;
263              }
264            
265            if (seg == null || seg.array == null || seg.count == 0)
266              continue;
267            
268            int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
269            if (width > span)
270              {
271                longestLine = child;
272                span = width;
273              }
274          }
275        maxLineLength = span;
276        return maxLineLength;
277      }
278      
279    public float getPreferredSpan(int axis)    public float getPreferredSpan(int axis)
280    {    {
281      if (axis != X_AXIS && axis != Y_AXIS)      if (axis != X_AXIS && axis != Y_AXIS)
# Line 217  public class PlainView extends View Line 286  public class PlainView extends View
286    
287      float span = 0;      float span = 0;
288      Element el = getElement();      Element el = getElement();
     Document doc = el.getDocument();  
     Segment seg = new Segment();  
289    
290      switch (axis)      switch (axis)
291        {        {
292        case X_AXIS:        case X_AXIS:
293          // calculate the maximum of the line's widths          span = determineMaxLineLength();
         for (int i = 0; i < el.getElementCount(); i++)  
           {  
             Element child = el.getElement(i);  
             int start = child.getStartOffset();  
             int end = child.getEndOffset();  
             try {  
               doc.getText(start, start + end, seg);  
             }  
             catch (BadLocationException ex)  
               {  
                 // throw new ClasspathAssertionError  
                 // ("no BadLocationException should be thrown here");  
               }  
             int width = metrics.charsWidth(seg.array, seg.offset, seg.count);  
             span = Math.max(span, width);  
           }  
         break;  
294        case Y_AXIS:        case Y_AXIS:
295        default:        default:
296          span = metrics.getHeight() * el.getElementCount();          span = metrics.getHeight() * el.getElementCount();
297          break;          break;
298        }        }
   
299      return span;      return span;
300    }    }
301    
# Line 264  public class PlainView extends View Line 313  public class PlainView extends View
313     */     */
314    public int viewToModel(float x, float y, Shape a, Position.Bias[] b)    public int viewToModel(float x, float y, Shape a, Position.Bias[] b)
315    {    {
316      // FIXME: not implemented      Rectangle rec = a.getBounds();
317      return 0;      Document doc = getDocument();
318        Element root = doc.getDefaultRootElement();
319        
320        // PlainView doesn't support line-wrapping so we can find out which
321        // Element was clicked on just by the y-position    
322        int lineClicked = (int) (y - rec.y) / metrics.getHeight();
323        if (lineClicked >= root.getElementCount())
324          return getEndOffset() - 1;
325        
326        Element line = root.getElement(lineClicked);
327        Segment s = getLineBuffer();
328    
329        int start = line.getStartOffset();
330        int end = line.getEndOffset();
331        try
332        {
333          doc.getText(start, end - start, s);
334        }
335        catch (BadLocationException ble)
336        {
337          AssertionError ae = new AssertionError("Unexpected bad location");
338          ae.initCause(ble);
339          throw ae;
340        }
341        
342        int pos = Utilities.getTabbedTextOffset(s, metrics, rec.x, (int)x, this, start);
343        return Math.max (0, pos);
344      }    
345      
346      /**
347       * Since insertUpdate and removeUpdate each deal with children
348       * Elements being both added and removed, they both have to perform
349       * the same checks.  So they both simply call this method.
350       * @param changes the DocumentEvent for the changes to the Document.
351       * @param a the allocation of the View.
352       * @param f the ViewFactory to use for rebuilding.
353       */
354      protected void updateDamage(DocumentEvent changes, Shape a, ViewFactory f)
355      {
356        Element el = getElement();
357        ElementChange ec = changes.getChange(el);
358        
359        // If ec is null then no lines were added or removed, just
360        // repaint the changed line
361        if (ec == null)
362          {
363            int line = getElement().getElementIndex(changes.getOffset());
364            damageLineRange(line, line, a, getContainer());
365            return;
366          }
367        
368        Element[] removed = ec.getChildrenRemoved();
369        Element[] newElements = ec.getChildrenAdded();
370        
371        // If no Elements were added or removed, we just want to repaint
372        // the area containing the line that was modified
373        if (removed == null && newElements == null)
374          {
375            int line = getElement().getElementIndex(changes.getOffset());
376            damageLineRange(line, line, a, getContainer());
377            return;
378          }
379    
380        // Check to see if we removed the longest line, if so we have to
381        // search through all lines and find the longest one again
382        if (removed != null)
383          {
384            for (int i = 0; i < removed.length; i++)
385              if (removed[i].equals(longestLine))
386                {
387                  // reset maxLineLength and search through all lines for longest one
388                  maxLineLength = -1;
389                  determineMaxLineLength();
390                  ((JTextComponent)getContainer()).repaint();
391                  return;
392                }
393          }
394        
395        // If we've reached here, that means we haven't removed the longest line
396        if (newElements == null)
397          {
398            // No lines were added, just repaint the container and exit
399            ((JTextComponent)getContainer()).repaint();
400            return;
401          }
402    
403        //  Make sure we have the metrics
404        updateMetrics();
405          
406        // If we've reached here, that means we haven't removed the longest line
407        // and we have added at least one line, so we have to check if added lines
408        // are longer than the previous longest line        
409        Segment seg = getLineBuffer();
410        float longestNewLength = 0;
411        Element longestNewLine = null;    
412    
413        // Loop through the added lines to check their length
414        for (int i = 0; i < newElements.length; i++)
415          {
416            Element child = newElements[i];
417            int start = child.getStartOffset();
418            int end = child.getEndOffset();
419            try
420              {
421                el.getDocument().getText(start, end - start, seg);
422              }
423            catch (BadLocationException ex)
424              {
425                AssertionError ae = new AssertionError("Unexpected bad location");
426                ae.initCause(ex);
427                throw ae;
428              }
429                    
430            if (seg == null || seg.array == null || seg.count == 0)
431              continue;
432            
433            int width = metrics.charsWidth(seg.array, seg.offset, seg.count);
434            if (width > longestNewLength)
435              {
436                longestNewLine = child;
437                longestNewLength = width;
438              }
439          }
440        
441        // Check if the longest of the new lines is longer than our previous
442        // longest line, and if so update our values
443        if (longestNewLength > maxLineLength)
444          {
445            maxLineLength = longestNewLength;
446            longestLine = longestNewLine;
447          }
448        // Repaint the container
449        ((JTextComponent)getContainer()).repaint();
450      }
451    
452      /**
453       * This method is called when something is inserted into the Document
454       * that this View is displaying.
455       *
456       * @param changes the DocumentEvent for the changes.
457       * @param a the allocation of the View
458       * @param f the ViewFactory used to rebuild
459       */
460      public void insertUpdate(DocumentEvent changes, Shape a, ViewFactory f)
461      {
462        updateDamage(changes, a, f);
463      }
464    
465      /**
466       * This method is called when something is removed from the Document
467       * that this View is displaying.
468       *
469       * @param changes the DocumentEvent for the changes.
470       * @param a the allocation of the View
471       * @param f the ViewFactory used to rebuild
472       */
473      public void removeUpdate(DocumentEvent changes, Shape a, ViewFactory f)
474      {
475        updateDamage(changes, a, f);
476      }
477      
478      /**
479       * This method is called when attributes were changed in the
480       * Document in a location that this view is responsible for.
481       */
482      public void changedUpdate (DocumentEvent changes, Shape a, ViewFactory f)
483      {
484        updateDamage(changes, a, f);
485      }
486      
487      /**
488       * Repaint the given line range.  This is called from insertUpdate,
489       * changedUpdate, and removeUpdate when no new lines were added
490       * and no lines were removed, to repaint the line that was
491       * modified.
492       *
493       * @param line0 the start of the range
494       * @param line1 the end of the range
495       * @param a the rendering region of the host
496       * @param host the Component that uses this View (used to call repaint
497       * on that Component)
498       *
499       * @since 1.4
500       */
501      protected void damageLineRange (int line0, int line1, Shape a, Component host)
502      {
503        if (a == null)
504          return;
505    
506        Rectangle rec0 = lineToRect(a, line0);
507        Rectangle rec1 = lineToRect(a, line1);
508    
509        if (rec0 == null || rec1 == null)
510          // something went wrong, repaint the entire host to be safe
511          host.repaint();
512        else
513          {
514            Rectangle repaintRec = rec0.union(rec1);
515            host.repaint();
516          }    
517      }
518    
519      /**
520       * Provides a {@link Segment} object, that can be used to fetch text from
521       * the document.
522       *
523       * @returna {@link Segment} object, that can be used to fetch text from
524       *          the document
525       */
526      protected Segment getLineBuffer()
527      {
528        if (lineBuffer == null)
529          lineBuffer = new Segment();
530        return lineBuffer;
531    }    }
532  }  }
533    

Legend:
Removed from v.1.1.2.9  
changed lines
  Added in v.1.1.2.10

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26