339 super.tickMarksUpdated(); 340 // recalculate minor tick marks 341 minorTickMarkValues = calculateMinorTickMarks(); 342 } 343 344 /** 345 * Invoked during the layout pass to layout this axis and all its content. 346 */ 347 @Override protected void layoutChildren() { 348 final Side side = getEffectiveSide(); 349 final double length = side.isVertical() ? getHeight() :getWidth() ; 350 // if we are not auto ranging we need to calculate the new scale 351 if(!isAutoRanging()) { 352 // calculate new scale 353 setScale(calculateNewScale(length, getLowerBound(), getUpperBound())); 354 // update current lower bound 355 currentLowerBound.set(getLowerBound()); 356 } 357 // we have done all auto calcs, let Axis position major tickmarks 358 super.layoutChildren(); 359 360 // Update minor tickmarks 361 minorTickPath.getElements().clear(); 362 363 double minorTickLength = Math.max(0, getMinorTickLength()); 364 // The length must be greater then the space required for tick marks, otherwise, there's no reason to create 365 // minor tick marks 366 if (minorTickLength > 0 && length > 2 * getTickMarks().size()) { 367 // Strip factor is >= 1. When == 1, all minor ticks will fit. 368 // It's computed as number of minor tick marks divided by available length 369 int stripFactor = (int)Math.ceil(2 * minorTickMarkValues.size() / (length - 2 * getTickMarks().size())); 370 if (Side.LEFT.equals(side)) { 371 // snap minorTickPath to pixels 372 minorTickPath.setLayoutX(-0.5); 373 minorTickPath.setLayoutY(0.5); 374 for (int i = 0; i < minorTickMarkValues.size(); i += stripFactor) { 375 T value = minorTickMarkValues.get(i); 376 double y = getDisplayPosition(value); 377 if (y >= 0 && y <= length) { 378 minorTickPath.getElements().addAll( 379 new MoveTo(getWidth() - minorTickLength, y), 380 new LineTo(getWidth() - 1, y)); 381 } 382 } 383 } else if (Side.RIGHT.equals(side)) { 384 // snap minorTickPath to pixels 385 minorTickPath.setLayoutX(0.5); 386 minorTickPath.setLayoutY(0.5); 387 for (int i = 0; i < minorTickMarkValues.size(); i += stripFactor) { 388 T value = minorTickMarkValues.get(i); 389 double y = getDisplayPosition(value); 390 if (y >= 0 && y <= length) { 391 minorTickPath.getElements().addAll( 392 new MoveTo(1, y), 393 new LineTo(minorTickLength, y)); 394 } 395 } 396 } else if (Side.TOP.equals(side)) { 397 // snap minorTickPath to pixels 398 minorTickPath.setLayoutX(0.5); 399 minorTickPath.setLayoutY(-0.5); 400 for (int i = 0; i < minorTickMarkValues.size(); i += stripFactor) { 401 T value = minorTickMarkValues.get(i); 402 double x = getDisplayPosition(value); 403 if (x >= 0 && x <= length) { 404 minorTickPath.getElements().addAll( 405 new MoveTo(x, getHeight() - 1), 406 new LineTo(x, getHeight() - minorTickLength)); 407 } 408 } 409 } else { // BOTTOM 410 // snap minorTickPath to pixels 411 minorTickPath.setLayoutX(0.5); 412 minorTickPath.setLayoutY(0.5); 413 for (int i = 0; i < minorTickMarkValues.size(); i += stripFactor) { 414 T value = minorTickMarkValues.get(i); 415 double x = getDisplayPosition(value); 416 if (x >= 0 && x <= length) { 417 minorTickPath.getElements().addAll( 418 new MoveTo(x, 1.0F), 419 new LineTo(x, minorTickLength)); 420 } 421 } 422 } 423 } 424 } 425 426 // -------------- METHODS ------------------------------------------------------------------------------------------ 427 428 /** 429 * Called when data has changed and the range may not be valid any more. This is only called by the chart if 430 * isAutoRanging() returns true. If we are auto ranging it will cause layout to be requested and auto ranging to 431 * happen on next layout pass. 432 * 433 * @param data The current set of all data that needs to be plotted on this axis 434 */ | 339 super.tickMarksUpdated(); 340 // recalculate minor tick marks 341 minorTickMarkValues = calculateMinorTickMarks(); 342 } 343 344 /** 345 * Invoked during the layout pass to layout this axis and all its content. 346 */ 347 @Override protected void layoutChildren() { 348 final Side side = getEffectiveSide(); 349 final double length = side.isVertical() ? getHeight() :getWidth() ; 350 // if we are not auto ranging we need to calculate the new scale 351 if(!isAutoRanging()) { 352 // calculate new scale 353 setScale(calculateNewScale(length, getLowerBound(), getUpperBound())); 354 // update current lower bound 355 currentLowerBound.set(getLowerBound()); 356 } 357 // we have done all auto calcs, let Axis position major tickmarks 358 super.layoutChildren(); 359 int numMinorTicks = (getTickMarks().size() - 1)*(Math.max(1, getMinorTickCount()) - 1); 360 double neededLength = (getTickMarks().size()+numMinorTicks)*2; 361 362 // Update minor tickmarks 363 minorTickPath.getElements().clear(); 364 // Don't draw minor tick marks if there isn't enough space for them! 365 366 double minorTickLength = Math.max(0, getMinorTickLength()); 367 if (minorTickLength > 0 && length > neededLength) { 368 if (Side.LEFT.equals(side)) { 369 // snap minorTickPath to pixels 370 minorTickPath.setLayoutX(-0.5); 371 minorTickPath.setLayoutY(0.5); 372 for (T value : minorTickMarkValues) { 373 double y = getDisplayPosition(value); 374 if (y >= 0 && y <= length) { 375 minorTickPath.getElements().addAll( 376 new MoveTo(getWidth() - minorTickLength, y), 377 new LineTo(getWidth() - 1, y)); 378 } 379 } 380 } else if (Side.RIGHT.equals(side)) { 381 // snap minorTickPath to pixels 382 minorTickPath.setLayoutX(0.5); 383 minorTickPath.setLayoutY(0.5); 384 for (T value : minorTickMarkValues) { 385 double y = getDisplayPosition(value); 386 if (y >= 0 && y <= length) { 387 minorTickPath.getElements().addAll( 388 new MoveTo(1, y), 389 new LineTo(minorTickLength, y)); 390 } 391 } 392 } else if (Side.TOP.equals(side)) { 393 // snap minorTickPath to pixels 394 minorTickPath.setLayoutX(0.5); 395 minorTickPath.setLayoutY(-0.5); 396 for (T value : minorTickMarkValues) { 397 double x = getDisplayPosition(value); 398 if (x >= 0 && x <= length) { 399 minorTickPath.getElements().addAll( 400 new MoveTo(x, getHeight() - 1), 401 new LineTo(x, getHeight() - minorTickLength)); 402 } 403 } 404 } else { // BOTTOM 405 // snap minorTickPath to pixels 406 minorTickPath.setLayoutX(0.5); 407 minorTickPath.setLayoutY(0.5); 408 for (T value : minorTickMarkValues) { 409 double x = getDisplayPosition(value); 410 if (x >= 0 && x <= length) { 411 minorTickPath.getElements().addAll( 412 new MoveTo(x, 1.0F), 413 new LineTo(x, minorTickLength)); 414 } 415 } 416 } 417 } 418 } 419 420 // -------------- METHODS ------------------------------------------------------------------------------------------ 421 422 /** 423 * Called when data has changed and the range may not be valid any more. This is only called by the chart if 424 * isAutoRanging() returns true. If we are auto ranging it will cause layout to be requested and auto ranging to 425 * happen on next layout pass. 426 * 427 * @param data The current set of all data that needs to be plotted on this axis 428 */ |