📄 scrollableobject.java
字号:
// synchronize tImages_all with tImages[] // remove unneeded tImage[ img_idx ] from tImages_all if ( ! tImages_all.remove( tImages[ img_idx ] ) ) System.err.println( "ScrollableObject: " + "checkToScrollView() " + "tImages[" + img_idx + "] = " + tImages[ img_idx ] + " does NOT " + "cover the end of tImages_all = " + tImages_all ); if ( img_mv_dir > 0 ) { past_img_idx = getNearPastImageIndex( img_idx ); tImages[ img_idx ].setEarliestTime( tImages[ past_img_idx ].getLatestTime() ); tImages[ img_idx ].setLatestFromEarliest( tImage_extent ); } else { // img_mv_dir < 0 future_img_idx = getNearFutureImageIndex( img_idx ); tImages[ img_idx ].setLatestTime( tImages[ future_img_idx ].getEarliestTime() ); tImages[ img_idx ].setEarliestFromLatest( tImage_extent ); } // update tImages_all to reflect changes in tImages[] // so drawOneOffImage() can use tImages_all tImages_all.affectTimeBounds( tImages[ img_idx ] ); } // Update the offscreenImages[] of those scrolled initializeAllOffImages( tImages_all ); if ( img_mv_dir > 0 ) //for ( idx = 1; idx <= Math.abs( Nimages_moved ); idx++ ) { for ( idx = Math.abs( Nimages_moved ); idx >=1; idx-- ) { img_idx = getValidImageIndex( start_idx + img_mv_dir * idx ); if ( offscreenImages[ img_idx ] != null ) drawOneOffImage( offscreenImages[ img_idx ], tImages[ img_idx ] ); } else for ( idx = 1; idx <= Math.abs( Nimages_moved ); idx++ ) { img_idx = getValidImageIndex( start_idx + img_mv_dir * idx ); if ( offscreenImages[ img_idx ] != null ) drawOneOffImage( offscreenImages[ img_idx ], tImages[ img_idx ] ); } finalizeAllOffImages( tImages_all ); // Update cur_img_idx in the offscreenImages[] cur_img_idx = getValidImageIndex( cur_img_idx + Nimages_moved ); } else { // Math.abs( Nimages_moved ) > NumImages if ( Debug.isActive() ) { Debug.println( "****************************************" ); Debug.println( "ScrollableObject: checkToScrollView() " + "| Nimages_moved( " + Nimages_moved + " ) | >= NumImages( " + NumImages + " )" ); } setImagesInitTimeBounds(); initializeAllOffImages( tImages_all ); for ( img_idx = 0; img_idx < NumImages; img_idx++ ) // for ( img_idx = NumImages-1; img_idx >=0; img_idx-- ) drawOneOffImage( offscreenImages[ img_idx ], tImages[ img_idx ] ); finalizeAllOffImages( tImages_all ); } } // Endof if ( Nimages_moved != 0 ) if ( Debug.isActive() ) Debug.println( "ScrollableObject: checkToScrollView()'s END: " ); } protected int time2pixel( double time_coord ) { return (int) Math.round( ( time_coord - tImages_all.getEarliestTime() ) * model.getViewPixelsPerUnitTime() ); } protected double pixel2time( int pixel_coord ) { return (double) pixel_coord / model.getViewPixelsPerUnitTime() + tImages_all.getEarliestTime(); } // scrollable_image interface. This returns pixel coordinate in the image // buffer measured from the far left of the buffer. public int getXaxisViewPosition() { if ( Debug.isActive() ) Debug.println( "ScrollableObject: getViewPosition() : " + "model.getTimeViewPosition()=" + model.getTimeViewPosition() ); return time2pixel( model.getTimeViewPosition() ); } /* images_endtimes: endtimes of the collective OffSreenImageS, offImage[] */ protected abstract void initializeAllOffImages( final TimeBoundingBox images_endtimes ); /* image_endtimes: endtimes of the OffScreenImage, image */ protected abstract void drawOneOffImage( Image image, final TimeBoundingBox image_endtimes ); /* images_endtimes: endtimes of the collective OffSreenImageS, offImage[] */ protected abstract void finalizeAllOffImages( final TimeBoundingBox images_endtimes ); public void paintComponent( Graphics g ) { if ( Debug.isActive() ) { Debug.println( "ScrollableObject : paintComponent()'s START : " ); Debug.println( "ScrollableObject : paintComponent() " + "g.getClipBounds() = " + g.getClipBounds() ); Debug.println( "ScrollableObject : paintComponent() " + "this = " + this ); if ( src_vport != null ) Debug.println( "ScrollableObject: paintComponent() " + "src_vport.getViewPosition() = " + src_vport.getViewPosition() ); } /* // These statements are moved to componentResized() // if ( offscreenImage == null ) { // offscreenImage = this.createImage( null ); // drawOneOffImage( offscreenImage ); // } */ int img_width, vport_mv_dir; int img_idx, screen_img_pos; int side_idx, side_bit, side_offset; // vport_mv_dir = viewport's moving direction vport_mv_dir = model.getViewportMovingDir(); if ( vport_mv_dir < 0 ) vport_mv_dir = -1; else vport_mv_dir = 1; img_width = image_size.width; // draw Image in the middle of offscreenImages[] img_idx = cur_img_idx; screen_img_pos = half_NumImages * img_width; if ( offscreenImages[ img_idx ] != null ) g.drawImage( offscreenImages[ img_idx ], screen_img_pos, 0, this ); // Images are drawn alternatively around the middle of // offscreenImages[]. The drawing starts with image in the // same direction as viewport moving direction(i.e. opposite // to image moving direction), then jumps to the image on the // other side of the middle image in the image buffer. // // The order of drawing aims to optimize the refresh rate of // image in the buffer, so that user does NOT notice the image // is being redrawn. The code is written to anticipate what // user wants to see next in the image buffer. The assumption // is that when viewport moves, it will be more likely to keep // moving in the same direction. for ( side_idx = 1; side_idx <= half_NumImages; side_idx++ ) { for ( side_bit = 1; side_bit >= -1; side_bit -= 2 ) { // viewport_move_direction = -1 * image_move_direction side_offset = side_bit * vport_mv_dir * side_idx; img_idx = getValidImageIndex( cur_img_idx + side_offset ); if ( Debug.isActive() ) Debug.println( "ScrollableObject: paintComponent() " + "side_offset = " + side_offset + ", " + "img_idx = " + img_idx ); screen_img_pos = ( half_NumImages + side_offset ) * img_width; if ( offscreenImages[ img_idx ] != null ) g.drawImage( offscreenImages[ img_idx ], screen_img_pos, 0, this ); } } if ( Debug.isActive() ) Debug.println( "ScrollableObject : paintComponent()'s END : " ); } public abstract int getJComponentHeight(); /* componentResized() seems to be always been called when (or right after) the object is created. Therefore, creatImage(), hence setSize(), are called inside componentResized(). */ // scrollable_image interface when the viewport is resized. public void componentResized( JViewport viewport ) { /* The offscreenImage cannot be created inside the constructor, because image size cannot be determined before the object is created */ if ( Debug.isActive() ) { Debug.println( "ScrollableObject: componentResized()'s START: " ); Debug.println( "incoming viewport = " + viewport ); } src_vport = viewport; if ( src_vport != null ) { visible_size = src_vport.getExtentSize(); if ( Debug.isActive() ) Debug.println( "ScrollableObject: componentResized()'s " + "src_vport.getViewPosition() = " + src_vport.getViewPosition() ); } else visible_size = getVisibleRect().getSize(); image_size.setSize( visible_size.width * NumViewsPerImage, getJComponentHeight() ); int NumOKImages = 0; for ( int img_idx = 0; img_idx < NumImages; img_idx++ ) { offscreenImages[ img_idx ] = this.createImage( image_size ); if ( offscreenImages[ img_idx ] != null ) NumOKImages += 1; } /* Init. of Time Model: Update the model's pixel coordinates. of time model during startup requires existence of offscreen image for its to do fireTimeChanged() to ViewportTime. i.e. model.updatePixelCoords() does model.fireTimeChanged() */ if ( NumOKImages == NumImages && visible_size.width > 0 ) { model.setViewPixelsPerUnitTime( visible_size.width ); model.updatePixelCoords(); } /* It is very IMPORTANT to setSize() to indicate the width of this JComponent is longer than the viewport size, so the JViewport.setViewPosition() will work when it scrolls to position wider than the viewport size, i.e. without cutoff. Defining getSize() for this class does NOT seem to help during initialization. setSize() is a must here in componentResize() */ component_size.setSize( image_size.width * NumImages, image_size.height ); setSize( component_size ); // compute the last image index in the image buffer int img_idx = getValidImageIndex( cur_img_idx + half_NumImages + 1 ); initializeAllOffImages( tImages_all ); for ( int idx = 0; idx < NumImages; idx++ ) { drawOneOffImage( offscreenImages[ img_idx ], tImages[ img_idx ] ); // img_idx = getNearPastImageIndex( img_idx ); img_idx = getNearFutureImageIndex( img_idx ); } finalizeAllOffImages( tImages_all ); if ( Debug.isActive() ) Debug.println( "ScrollableObject: componentResized()'s END: " ); } /* This method is for HierarchyBoundsListener, i.e ancestorMoved() or ancestorResized() methods. setJComponentSize() becomes irrelvant after defining getPreferredSize() */ /* public void setJComponentSize() { setSize( component_size ); } */ /* Defining getPreferredSize() seems to make HierarchyBoundsListener for ViewportTime unnecessary. */ public Dimension getPreferredSize() { if ( Debug.isActive() ) Debug.println( "ScrollableObject: pref_size = " + component_size ); return component_size; } public Dimension getSize() { if ( Debug.isActive() ) Debug.println( "ScrollableObject: size = " + component_size ); return component_size; } // Override the Component.setCursor() public void setCursor( Cursor new_cursor ) { /* Make sure that the Cursor of this Component is not set, so the Cursor of its parent, ViewportTime, determines the cursor of the component. */ // super.setCursor( null ); } public abstract InfoDialog getPropertyAt( final Point view_click, final TimeBoundingBox vport_times ); /* protected Point getGlobalClickPoint( final Point local_click ) { Point origin = this.getLocationOnScreen(); return new Point( origin.x + local_click.x, origin.y + local_click.y ); } */ protected InfoDialog getTimePropertyAt( final Point local_click ) { /* System.out.println( "\nshowPropertyAt() " + local_click ); */ CoordPixelImage coord_xform; coord_xform = new CoordPixelImage( this, 0, this.getTimeBoundsOfImages() ); Window window; window = SwingUtilities.windowForComponent( this ); if ( window instanceof Frame ) return new InfoDialogForTime( (Frame) window, coord_xform.convertPixelToTime( local_click.x ) ); else // if ( window instanceof Dialog ) return new InfoDialogForTime( (Dialog) window, coord_xform.convertPixelToTime( local_click.x ) ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -