Audacity 3.2.0
Public Member Functions | Public Attributes | List of all members
Ruler::TickSizes Struct Reference

Public Member Functions

 TickSizes (double UPP, int orientation, RulerFormat format, bool log)
 
TranslatableString LabelString (double d, RulerFormat format, const TranslatableString &units) const
 

Public Attributes

bool useMajor = true
 
double mMajor
 
double mMinor
 
int mDigits
 

Detailed Description

Definition at line 357 of file Ruler.cpp.

Constructor & Destructor Documentation

◆ TickSizes()

Ruler::TickSizes::TickSizes ( double  UPP,
int  orientation,
RulerFormat  format,
bool  log 
)
inline

Definition at line 366 of file Ruler.cpp.

367{
368 //TODO: better dynamic digit computation for the log case
369 (void)log;
370
371 // Given the dimensions of the ruler, the range of values it
372 // has to display, and the format (i.e. Int, Real, Time),
373 // figure out how many units are in one Minor tick, and
374 // in one Major tick.
375 //
376 // The goal is to always put tick marks on nice round numbers
377 // that are easy for humans to grok. This is the most tricky
378 // with time.
379
380 double d;
381
382 // As a heuristic, we want at least 22 pixels between each
383 // minor tick. We want to show numbers like "-48"
384 // in that space.
385 // If vertical, we don't need as much space.
386 double units = ((orientation == wxHORIZONTAL) ? 22 : 16) * fabs(UPP);
387
388 mDigits = 0;
389
390 switch(format) {
391 case LinearDBFormat:
392 if (units < 0.001) {
393 mMinor = 0.001;
394 mMajor = 0.005;
395 return;
396 }
397 if (units < 0.01) {
398 mMinor = 0.01;
399 mMajor = 0.05;
400 return;
401 }
402 if (units < 0.1) {
403 mMinor = 0.1;
404 mMajor = 0.5;
405 return;
406 }
407 if (units < 1.0) {
408 mMinor = 1.0;
409 mMajor = 6.0;
410 return;
411 }
412 if (units < 3.0) {
413 mMinor = 3.0;
414 mMajor = 12.0;
415 return;
416 }
417 if (units < 6.0) {
418 mMinor = 6.0;
419 mMajor = 24.0;
420 return;
421 }
422 if (units < 12.0) {
423 mMinor = 12.0;
424 mMajor = 48.0;
425 return;
426 }
427 if (units < 24.0) {
428 mMinor = 24.0;
429 mMajor = 96.0;
430 return;
431 }
432 d = 20.0;
433 for(;;) {
434 if (units < d) {
435 mMinor = d;
436 mMajor = d*5.0;
437 return;
438 }
439 d *= 5.0;
440 if (units < d) {
441 mMinor = d;
442 mMajor = d*5.0;
443 return;
444 }
445 d *= 2.0;
446 }
447 break;
448
449 case IntFormat:
450 d = 1.0;
451 for(;;) {
452 if (units < d) {
453 mMinor = d;
454 mMajor = d*5.0;
455 return;
456 }
457 d *= 5.0;
458 if (units < d) {
459 mMinor = d;
460 mMajor = d*2.0;
461 return;
462 }
463 d *= 2.0;
464 }
465 break;
466
467 case TimeFormat:
468 if (units > 0.5) {
469 if (units < 1.0) { // 1 sec
470 mMinor = 1.0;
471 mMajor = 5.0;
472 return;
473 }
474 if (units < 5.0) { // 5 sec
475 mMinor = 5.0;
476 mMajor = 15.0;
477 return;
478 }
479 if (units < 10.0) {
480 mMinor = 10.0;
481 mMajor = 30.0;
482 return;
483 }
484 if (units < 15.0) {
485 mMinor = 15.0;
486 mMajor = 60.0;
487 return;
488 }
489 if (units < 30.0) {
490 mMinor = 30.0;
491 mMajor = 60.0;
492 return;
493 }
494 if (units < 60.0) { // 1 min
495 mMinor = 60.0;
496 mMajor = 300.0;
497 return;
498 }
499 if (units < 300.0) { // 5 min
500 mMinor = 300.0;
501 mMajor = 900.0;
502 return;
503 }
504 if (units < 600.0) { // 10 min
505 mMinor = 600.0;
506 mMajor = 1800.0;
507 return;
508 }
509 if (units < 900.0) { // 15 min
510 mMinor = 900.0;
511 mMajor = 3600.0;
512 return;
513 }
514 if (units < 1800.0) { // 30 min
515 mMinor = 1800.0;
516 mMajor = 3600.0;
517 return;
518 }
519 if (units < 3600.0) { // 1 hr
520 mMinor = 3600.0;
521 mMajor = 6*3600.0;
522 return;
523 }
524 if (units < 6*3600.0) { // 6 hrs
525 mMinor = 6*3600.0;
526 mMajor = 24*3600.0;
527 return;
528 }
529 if (units < 24*3600.0) { // 1 day
530 mMinor = 24*3600.0;
531 mMajor = 7*24*3600.0;
532 return;
533 }
534
535 mMinor = 24.0 * 7.0 * 3600.0; // 1 week
536 mMajor = 24.0 * 7.0 * 3600.0;
537 }
538
539 // Otherwise fall through to RealFormat
540 // (fractions of a second should be dealt with
541 // the same way as for RealFormat)
542
543 case RealFormat:
544 d = 0.000001;
545 // mDigits is number of digits after the decimal point.
546 mDigits = 6;
547 for(;;) {
548 if (units < d) {
549 mMinor = d;
550 mMajor = d*5.0;
551 return;
552 }
553 d *= 5.0;
554 if (units < d) {
555 mMinor = d;
556 mMajor = d*2.0;
557 return;
558 }
559 d *= 2.0;
560 mDigits--;
561 // More than 10 digit numbers? Something is badly wrong.
562 // Probably units is coming in with too high a value.
563 wxASSERT( mDigits >= -10 );
564 if( mDigits < -10 )
565 break;
566 }
567 mMinor = d;
568 mMajor = d * 2.0;
569 break;
570
571 case RealLogFormat:
572 d = 0.000001;
573 // mDigits is number of digits after the decimal point.
574 mDigits = 6;
575 for(;;) {
576 if (units < d) {
577 mMinor = d;
578 mMajor = d*5.0;
579 return;
580 }
581 d *= 5.0;
582 if (units < d) {
583 mMinor = d;
584 mMajor = d*2.0;
585 return;
586 }
587 d *= 2.0;
588 mDigits--;
589 // More than 10 digit numbers? Something is badly wrong.
590 // Probably units is coming in with too high a value.
591 wxASSERT( mDigits >= -10 );
592 if( mDigits < -10 )
593 break;
594 }
595 mDigits++;
596 mMinor = d;
597 mMajor = d * 2.0;
598 break;
599 }
600}
int format
Definition: ExportPCM.cpp:53
@ TimeFormat
Definition: Ruler.h:33
@ LinearDBFormat
Definition: Ruler.h:34
@ RealFormat
Definition: Ruler.h:31
@ IntFormat
Definition: Ruler.h:30
@ RealLogFormat
Definition: Ruler.h:32
double mMajor
Definition: Ruler.cpp:361
double mMinor
Definition: Ruler.cpp:362

References format, Ruler::IntFormat, Ruler::LinearDBFormat, mDigits, mMajor, mMinor, Ruler::RealFormat, Ruler::RealLogFormat, and Ruler::TimeFormat.

Member Function Documentation

◆ LabelString()

TranslatableString Ruler::TickSizes::LabelString ( double  d,
RulerFormat  format,
const TranslatableString units 
) const
inline

Definition at line 602 of file Ruler.cpp.

605{
606 // Given a value, turn it into a string according
607 // to the current ruler format. The number of digits of
608 // accuracy depends on the resolution of the ruler,
609 // i.e. how far zoomed in or out you are.
610
611 wxString s;
612
613 // PRL Todo: are all these cases properly localized? (Decimal points,
614 // hour-minute-second, etc.?)
615
616 // Replace -0 with 0
617 if (d < 0.0 && (d+mMinor > 0.0) && ( format != RealLogFormat ))
618 d = 0.0;
619
620 switch( format ) {
621 case IntFormat:
622 s.Printf(wxT("%d"), (int)floor(d+0.5));
623 break;
624 case LinearDBFormat:
625 if (mMinor >= 1.0)
626 s.Printf(wxT("%d"), (int)floor(d+0.5));
627 else {
628 int precision = -log10(mMinor);
629 s.Printf(wxT("%.*f"), precision, d);
630 }
631 break;
632 case RealFormat:
633 if (mMinor >= 1.0)
634 s.Printf(wxT("%d"), (int)floor(d+0.5));
635 else {
636 s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d);
637 }
638 break;
639 case RealLogFormat:
640 if (mMinor >= 1.0)
641 s.Printf(wxT("%d"), (int)floor(d+0.5));
642 else {
643 s.Printf(wxString::Format(wxT("%%.%df"), mDigits), d);
644 }
645 break;
646 case TimeFormat:
647 if (useMajor) {
648 if (d < 0) {
649 s = wxT("-");
650 d = -d;
651 }
652
653 #if ALWAYS_HH_MM_SS
654 int secs = (int)(d + 0.5);
655 if (mMinor >= 1.0) {
656 s.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60);
657 }
658 else {
659 wxString t1, t2, format;
660 t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60);
661 format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits);
662 t2.Printf(format, fmod(d, 60.0));
663 s += t1 + t2;
664 }
665 break;
666 #endif
667
668 if (mMinor >= 3600.0) {
669 int hrs = (int)(d / 3600.0 + 0.5);
670 wxString h;
671 h.Printf(wxT("%d:00:00"), hrs);
672 s += h;
673 }
674 else if (mMinor >= 60.0) {
675 int minutes = (int)(d / 60.0 + 0.5);
676 wxString m;
677 if (minutes >= 60)
678 m.Printf(wxT("%d:%02d:00"), minutes/60, minutes%60);
679 else
680 m.Printf(wxT("%d:00"), minutes);
681 s += m;
682 }
683 else if (mMinor >= 1.0) {
684 int secs = (int)(d + 0.5);
685 wxString t;
686 if (secs >= 3600)
687 t.Printf(wxT("%d:%02d:%02d"), secs/3600, (secs/60)%60, secs%60);
688 else if (secs >= 60)
689 t.Printf(wxT("%d:%02d"), secs/60, secs%60);
690 else
691 t.Printf(wxT("%d"), secs);
692 s += t;
693 }
694 else {
695// Commented out old and incorrect code for avoiding the 40mins and 60 seconds problem
696// It was causing Bug 463 - Incorrect Timeline numbering (where at high zoom and long tracks,
697// numbers did not change.
698#if 0
699 // The casting to float is working around an issue where 59 seconds
700 // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3.
701 int secs = (int)(float)(d);
702 wxString t1, t2, format;
703
704 if (secs >= 3600)
705 t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60);
706 else if (secs >= 60)
707 t1.Printf(wxT("%d:"), secs/60);
708
709 if (secs >= 60)
710 format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits);
711 else
712 format.Printf(wxT("%%%d.%dlf"), mDigits+3, mDigits);
713 // The casting to float is working around an issue where 59 seconds
714 // would show up as 60 when using g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3.
715 t2.Printf(format, fmod((float)d, (float)60.0));
716#else
717 // For d in the range of hours, d is just very slightly below the value it should
718 // have, because of using a double, which in turn yields values like 59:59:999999
719 // mins:secs:nanosecs when we want 1:00:00:000000
720 // so adjust by less than a nano second per hour to get nicer number formatting.
721 double dd = d * 1.000000000000001;
722 int secs = (int)(dd);
723 wxString t1, t2, format;
724
725 if (secs >= 3600)
726 t1.Printf(wxT("%d:%02d:"), secs/3600, (secs/60)%60);
727 else if (secs >= 60)
728 t1.Printf(wxT("%d:"), secs/60);
729
730 if (secs >= 60)
731 format.Printf(wxT("%%0%d.%dlf"), mDigits+3, mDigits);
732 else
733 format.Printf(wxT("%%%d.%dlf"), mDigits+3, mDigits);
734 // dd will be reduced to just the seconds and fractional part.
735 dd = dd - secs + (secs%60);
736 // truncate to appropriate number of digits, so that the print formatting
737 // doesn't round up 59.9999999 to 60.
738 double multiplier = pow( 10, mDigits);
739 dd = ((int)(dd * multiplier))/multiplier;
740 t2.Printf(format, dd);
741#endif
742 s += t1 + t2;
743 }
744 }
745 else {
746 }
747 }
748
749 auto result = Verbatim( s );
750 if (!units.empty())
751 result += units;
752
753 return result;
754}
wxT("CloseDown"))
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.

References TranslatableString::empty(), format, Ruler::IntFormat, Ruler::LinearDBFormat, mDigits, mMinor, Ruler::RealFormat, Ruler::RealLogFormat, Ruler::TimeFormat, useMajor, Verbatim(), and wxT().

Referenced by Ruler::Updater::Tick().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mDigits

int Ruler::TickSizes::mDigits

Definition at line 364 of file Ruler.cpp.

Referenced by LabelString(), and TickSizes().

◆ mMajor

double Ruler::TickSizes::mMajor

Definition at line 361 of file Ruler.cpp.

Referenced by TickSizes().

◆ mMinor

double Ruler::TickSizes::mMinor

Definition at line 362 of file Ruler.cpp.

Referenced by LabelString(), and TickSizes().

◆ useMajor

bool Ruler::TickSizes::useMajor = true

Definition at line 359 of file Ruler.cpp.

Referenced by LabelString().


The documentation for this struct was generated from the following file: