fortplot_figure_core_ticks.f90 Source File


Source Code

submodule (fortplot_figure_core) fortplot_figure_core_ticks
    !! Custom tick label operations for figure_t
    !!
    !! Single Responsibility: Handle custom tick positions and labels
    !! Extracted to maintain file size compliance

    use fortplot_logging, only: log_error, log_warning
    implicit none

contains

    module subroutine set_xticks(self, positions, labels)
        !! Set custom x-axis tick positions and optionally labels
        !! If only positions provided, numeric labels are auto-generated
        !! If both provided, custom string labels are used
        class(figure_t), intent(inout) :: self
        real(wp), intent(in) :: positions(:)
        character(len=*), intent(in), optional :: labels(:)

        integer :: n, i

        n = size(positions)
        if (n == 0) then
            call log_warning('set_xticks: empty positions array')
            return
        end if

        if (present(labels)) then
            if (size(labels) /= n) then
                call log_error('set_xticks: labels array size must match positions')
                return
            end if
        end if

        if (allocated(self%state%custom_xtick_positions)) &
            deallocate(self%state%custom_xtick_positions)
        if (allocated(self%state%custom_xtick_labels)) &
            deallocate(self%state%custom_xtick_labels)

        allocate(self%state%custom_xtick_positions(n))
        allocate(self%state%custom_xtick_labels(n))

        self%state%custom_xtick_positions = positions

        if (present(labels)) then
            do i = 1, n
                self%state%custom_xtick_labels(i) = trim(labels(i))
            end do
        else
            do i = 1, n
                write(self%state%custom_xtick_labels(i), '(G12.5)') positions(i)
                self%state%custom_xtick_labels(i) = &
                    adjustl(self%state%custom_xtick_labels(i))
            end do
        end if

        self%state%custom_xticks_set = .true.
        self%state%rendered = .false.
    end subroutine set_xticks

    module subroutine set_yticks(self, positions, labels)
        !! Set custom y-axis tick positions and optionally labels
        class(figure_t), intent(inout) :: self
        real(wp), intent(in) :: positions(:)
        character(len=*), intent(in), optional :: labels(:)

        integer :: n, i

        n = size(positions)
        if (n == 0) then
            call log_warning('set_yticks: empty positions array')
            return
        end if

        if (present(labels)) then
            if (size(labels) /= n) then
                call log_error('set_yticks: labels array size must match positions')
                return
            end if
        end if

        if (allocated(self%state%custom_ytick_positions)) &
            deallocate(self%state%custom_ytick_positions)
        if (allocated(self%state%custom_ytick_labels)) &
            deallocate(self%state%custom_ytick_labels)

        allocate(self%state%custom_ytick_positions(n))
        allocate(self%state%custom_ytick_labels(n))

        self%state%custom_ytick_positions = positions

        if (present(labels)) then
            do i = 1, n
                self%state%custom_ytick_labels(i) = trim(labels(i))
            end do
        else
            do i = 1, n
                write(self%state%custom_ytick_labels(i), '(G12.5)') positions(i)
                self%state%custom_ytick_labels(i) = &
                    adjustl(self%state%custom_ytick_labels(i))
            end do
        end if

        self%state%custom_yticks_set = .true.
        self%state%rendered = .false.
    end subroutine set_yticks

    module subroutine set_xtick_labels(self, labels)
        !! Set custom x-axis tick labels for current tick positions
        !! Use after bar() or set_xticks() to provide categorical labels
        class(figure_t), intent(inout) :: self
        character(len=*), intent(in) :: labels(:)

        integer :: n, i

        n = size(labels)
        if (n == 0) then
            call log_warning('set_xtick_labels: empty labels array')
            return
        end if

        if (allocated(self%state%custom_xtick_labels)) &
            deallocate(self%state%custom_xtick_labels)

        allocate(self%state%custom_xtick_labels(n))

        do i = 1, n
            self%state%custom_xtick_labels(i) = trim(labels(i))
        end do

        if (.not. allocated(self%state%custom_xtick_positions)) then
            allocate(self%state%custom_xtick_positions(n))
            do i = 1, n
                self%state%custom_xtick_positions(i) = real(i, wp)
            end do
        end if

        self%state%custom_xticks_set = .true.
        self%state%rendered = .false.
    end subroutine set_xtick_labels

    module subroutine set_ytick_labels(self, labels)
        !! Set custom y-axis tick labels for current tick positions
        class(figure_t), intent(inout) :: self
        character(len=*), intent(in) :: labels(:)

        integer :: n, i

        n = size(labels)
        if (n == 0) then
            call log_warning('set_ytick_labels: empty labels array')
            return
        end if

        if (allocated(self%state%custom_ytick_labels)) &
            deallocate(self%state%custom_ytick_labels)

        allocate(self%state%custom_ytick_labels(n))

        do i = 1, n
            self%state%custom_ytick_labels(i) = trim(labels(i))
        end do

        if (.not. allocated(self%state%custom_ytick_positions)) then
            allocate(self%state%custom_ytick_positions(n))
            do i = 1, n
                self%state%custom_ytick_positions(i) = real(i, wp)
            end do
        end if

        self%state%custom_yticks_set = .true.
        self%state%rendered = .false.
    end subroutine set_ytick_labels

end submodule fortplot_figure_core_ticks