1717package com .androidplot .ui .widget ;
1818
1919import android .graphics .*;
20+ import android .support .annotation .NonNull ;
21+ import android .support .annotation .Nullable ;
22+
2023import com .androidplot .exception .PlotRenderException ;
2124import com .androidplot .ui .*;
2225import com .androidplot .util .DisplayDimensions ;
@@ -42,6 +45,7 @@ public abstract class Widget implements BoxModelable, Resizable {
4245 private LayoutManager layoutManager ;
4346
4447 private Rotation rotation = Rotation .NONE ;
48+ private RectF lastWidgetRect = null ;
4549
4650 public enum Rotation {
4751 NINETY_DEGREES ,
@@ -77,6 +81,7 @@ public void setAnchor(Anchor anchor) {
7781 /**
7882 * Same as {@link #position(float, HorizontalPositioning, float, VerticalPositioning, Anchor)}
7983 * but with the anchor parameter defaulted to the upper left corner.
84+ *
8085 * @param x
8186 * @param horizontalPositioning
8287 * @param y
@@ -87,11 +92,11 @@ public void position(float x, HorizontalPositioning horizontalPositioning, float
8792 }
8893
8994 /**
90- * @param x X-Coordinate of the top left corner of element. When using RELATIVE, must be a value between 0 and 1.
95+ * @param x X-Coordinate of the top left corner of element. When using RELATIVE, must be a value between 0 and 1.
9196 * @param horizontalPositioning LayoutType to use when orienting this element's X-Coordinate.
92- * @param y Y_VALS_ONLY-Coordinate of the top-left corner of element. When using RELATIVE, must be a value between 0 and 1.
93- * @param verticalPositioning LayoutType to use when orienting this element's Y_VALS_ONLY-Coordinate.
94- * @param anchor The point of reference used by this positioning call.
97+ * @param y Y_VALS_ONLY-Coordinate of the top-left corner of element. When using RELATIVE, must be a value between 0 and 1.
98+ * @param verticalPositioning LayoutType to use when orienting this element's Y_VALS_ONLY-Coordinate.
99+ * @param anchor The point of reference used by this positioning call.
95100 */
96101 public void position (float x , HorizontalPositioning horizontalPositioning , float y ,
97102 VerticalPositioning verticalPositioning , Anchor anchor ) {
@@ -271,15 +276,15 @@ public float getMarginRight() {
271276 * into this Widget's size or position is altered.
272277 */
273278 public synchronized void refreshLayout () {
274- if (positionMetrics == null ) {
279+ if (positionMetrics == null ) {
275280 // make sure positionMetrics have been set. this method can be
276281 // automatically called during xml configuration of certain params
277282 // before the widget is fully configured.
278283 return ;
279284 }
280285 float elementWidth = getWidthPix (plotDimensions .paddedRect .width ());
281286 float elementHeight = getHeightPix (plotDimensions .paddedRect .height ());
282- PointF coords = getElementCoordinates (elementHeight ,
287+ PointF coords = calculateCoordinates (elementHeight ,
283288 elementWidth , plotDimensions .paddedRect , positionMetrics );
284289
285290 RectF widgetRect = new RectF (coords .x , coords .y ,
@@ -296,69 +301,90 @@ public synchronized void layout(final DisplayDimensions plotDimensions) {
296301 refreshLayout ();
297302 }
298303
299- public PointF getElementCoordinates (float height , float width , RectF viewRect , PositionMetrics metrics ) {
300- float x = metrics .getXPositionMetric ().getPixelValue (viewRect .width ()) + viewRect .left ;
301- float y = metrics .getYPositionMetric ().getPixelValue (viewRect .height ()) + viewRect .top ;
302- PointF point = new PointF (x , y );
303- return PixelUtils .sub (point , getAnchorOffset (width , height , metrics .getAnchor ()));
304- }
304+
305+ public static PointF calculateCoordinates (float height , float width , RectF viewRect , PositionMetrics metrics ) {
306+ float x = metrics .getXPositionMetric ().getPixelValue (viewRect .width ()) + viewRect .left ;
307+ float y = metrics .getYPositionMetric ().getPixelValue (viewRect .height ()) + viewRect .top ;
308+ PointF point = new PointF (x , y );
309+ return PixelUtils .sub (point , getAnchorOffset (width , height , metrics .getAnchor ()));
310+ }
305311
306312 public static PointF getAnchorOffset (float width , float height , Anchor anchor ) {
307- PointF point = new PointF ();
308- switch (anchor ) {
309- case LEFT_TOP :
310- break ;
311- case LEFT_MIDDLE :
312- point .set (0 , height / 2 );
313- break ;
314- case LEFT_BOTTOM :
315- point .set (0 , height );
316- break ;
317- case RIGHT_TOP :
318- point .set (width , 0 );
319- break ;
320- case RIGHT_BOTTOM :
321- point .set (width , height );
322- break ;
323- case RIGHT_MIDDLE :
324- point .set (width , height / 2 );
325- break ;
326- case TOP_MIDDLE :
327- point .set (width / 2 , 0 );
328- break ;
329- case BOTTOM_MIDDLE :
330- point .set (width / 2 , height );
331- break ;
332- case CENTER :
333- point .set (width / 2 , height / 2 );
334- break ;
335- default :
336- throw new IllegalArgumentException ("Unsupported anchor location: " + anchor );
337- }
338- return point ;
313+ PointF point = new PointF ();
314+ switch (anchor ) {
315+ case LEFT_TOP :
316+ break ;
317+ case LEFT_MIDDLE :
318+ point .set (0 , height / 2 );
319+ break ;
320+ case LEFT_BOTTOM :
321+ point .set (0 , height );
322+ break ;
323+ case RIGHT_TOP :
324+ point .set (width , 0 );
325+ break ;
326+ case RIGHT_BOTTOM :
327+ point .set (width , height );
328+ break ;
329+ case RIGHT_MIDDLE :
330+ point .set (width , height / 2 );
331+ break ;
332+ case TOP_MIDDLE :
333+ point .set (width / 2 , 0 );
334+ break ;
335+ case BOTTOM_MIDDLE :
336+ point .set (width / 2 , height );
337+ break ;
338+ case CENTER :
339+ point .set (width / 2 , height / 2 );
340+ break ;
341+ default :
342+ throw new IllegalArgumentException ("Unsupported anchor location: " + anchor );
339343 }
344+ return point ;
345+ }
340346
341347 public static PointF getAnchorCoordinates (RectF widgetRect , Anchor anchor ) {
342- return PixelUtils .add (new PointF (widgetRect .left , widgetRect .top ),
343- getAnchorOffset (widgetRect .width (), widgetRect .height (), anchor ));
344- }
348+ return PixelUtils .add (new PointF (widgetRect .left , widgetRect .top ),
349+ getAnchorOffset (widgetRect .width (), widgetRect .height (), anchor ));
350+ }
351+
352+ public static PointF getAnchorCoordinates (float x , float y , float width , float height , Anchor anchor ) {
353+ return getAnchorCoordinates (new RectF (x , y , x + width , y + height ), anchor );
354+ }
345355
346- public static PointF getAnchorCoordinates (float x , float y , float width , float height , Anchor anchor ) {
347- return getAnchorCoordinates (new RectF (x , y , x +width , y +height ), anchor );
356+ private void checkSize (@ NonNull RectF widgetRect ) {
357+ if (lastWidgetRect == null || !lastWidgetRect .equals (widgetRect )) {
358+ onResize (lastWidgetRect , widgetRect );
348359 }
360+ lastWidgetRect = widgetRect ;
361+ }
362+
363+ /**
364+ * Called whenever the height or width of the Widget's reserved space has changed,
365+ * immediately before {@link #doOnDraw(Canvas, RectF)}.
366+ * May be used to efficiently carry out expensive operations only when necessary.
367+ *
368+ * @param oldRect
369+ * @param newRect
370+ */
371+ protected void onResize (@ Nullable RectF oldRect , @ NonNull RectF newRect ) {
372+ // do nothing by default
373+ }
349374
350375 public void draw (Canvas canvas ) throws PlotRenderException {
351376 if (isVisible ()) {
352377 if (backgroundPaint != null ) {
353378 drawBackground (canvas , widgetDimensions .canvasRect );
354379 }
355380 canvas .save ();
356- final RectF paddedRect = applyRotation (canvas , widgetDimensions .paddedRect );
357- doOnDraw (canvas , paddedRect );
381+ final RectF widgetRect = applyRotation (canvas , widgetDimensions .paddedRect );
382+ checkSize (widgetRect );
383+ doOnDraw (canvas , widgetRect );
358384 canvas .restore ();
359385
360386 if (borderPaint != null ) {
361- drawBorder (canvas , paddedRect );
387+ drawBorder (canvas , widgetRect );
362388 }
363389 }
364390 }
@@ -395,7 +421,7 @@ protected RectF applyRotation(Canvas canvas, RectF rect) {
395421 throw new UnsupportedOperationException ("Not yet implemented." );
396422
397423 }
398- if (rotation != Rotation .NONE ) {
424+ if (rotation != Rotation .NONE ) {
399425 canvas .rotate (rotationDegs , cx , cy );
400426 }
401427 return rect ;
0 commit comments