R/try_area_methods.R

Defines functions try_area_full try_area_reduced try_area_shiny

try_area_shiny <- function(file, dims, area = NULL) {
  requireNamespace("shiny")
  requireNamespace("miniUI")

  ui <- miniUI::miniPage(
    miniUI::gadgetTitleBar("Click and drag to select an area. Click 'Done' to accept."),
    miniUI::miniContentPanel(
      padding = 0,
      shiny::plotOutput("plot", height = "100%", brush = shiny::brushOpts(id = "plot_brush"))
    )
  )
  server <- function(input, output, session) {
    thispng <- readPNG(file, native = TRUE)
    if (!length(area)) {
      startx <- NULL
      starty <- NULL
      endx <- NULL
      endy <- NULL
    } else {
      showArea <- function() {
        # convert from: top,left,bottom,right
        startx <<- area[2]
        starty <<- dims[2] - area[1]
        endx <<- area[4]
        endy <<- dims[2] - area[3]
        drawRectangle()
      }
      showArea()
    }
    drawPage <- function() {
      pre_par <- graphics::par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i", bty = "n")
      on.exit(graphics::par(pre_par), add = TRUE)
      graphics::plot(c(0, dims[1]), c(0, dims[2]), type = "n", xlab = "", ylab = "", asp = 1)
      graphics::rasterImage(thispng, 0, 0, dims[1], dims[2])
    }
    drawRectangle <- function() {
      if (!is.null(endx)) {
        graphics::rect(startx, starty, endx, endy, col = grDevices::rgb(1, 0, 0, .2))
      }
    }
    output$plot <- shiny::renderPlot({
      pre_par <- graphics::par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i", bty = "n")
      on.exit(graphics::par(pre_par), add = TRUE)
      drawPage()
      if (!is.null(input$plot_brush)) {
        startx <<- input$plot_brush$xmin
        endx <<- input$plot_brush$xmax
        starty <<- input$plot_brush$ymin
        endy <<- input$plot_brush$ymax
        drawRectangle()
      }
    })
    shiny::observeEvent(input$done, {
      if (is.null(startx)) {
        area <- NULL
      } else {
        # convert to: top,left,bottom,right
        area <- c(
          top = dims[2] - max(c(starty, endy)),
          left = min(c(startx, endx)),
          bottom = dims[2] - (min(c(starty, endy))),
          right = max(c(startx, endx))
        )
      }
      shiny::stopApp(list(key = "right", area = area))
    })
  }
  shiny::runGadget(shiny::shinyApp(ui = ui, server = server))
}

try_area_reduced <- function(file, dims, area = NULL, warn = FALSE) {
  if (warn) {
    message(
      "Graphics device does not support event handling...\n",
      "Entering reduced functionality mode.\n",
      "Click upper-left and then lower-right corners of area."
    )
  }
  if (grDevices::dev.capabilities()[["rasterImage"]] == "no") {
    stop("Graphics device does not support rasterImage() plotting")
  }
  thispng <- readPNG(file, native = TRUE)
  drawPage <- function() {
    graphics::plot(c(0, dims[1]), c(0, dims[2]), type = "n", xlab = "", ylab = "", asp = 1)
    graphics::rasterImage(thispng, 0, 0, dims[1], dims[2])
  }

  pre_par <- graphics::par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i", bty = "n")
  on.exit(graphics::par(pre_par), add = TRUE)
  drawPage()
  on.exit(grDevices::dev.off(), add = TRUE)

  tmp <- locator(2)
  graphics::rect(tmp$x[1], tmp$y[1], tmp$x[2], tmp$y[2], col = grDevices::rgb(1, 0, 0, .5))
  Sys.sleep(2)

  # convert to: top,left,bottom,right
  area <- c(dims[2] - max(tmp$y), min(tmp$x), dims[2] - min(tmp$y), max(tmp$x))
  return(list(key = "right", area = area))
}

try_area_full <- function(file, dims, area = NULL) {
  deviceUnits <- "nfc"
  if (Sys.info()["sysname"] == "Darwin") {
    grDevices::X11(type = "Xlib")
  }
  if (grDevices::dev.capabilities()[["rasterImage"]] == "no") {
    stop("Graphics device does not support rasterImage() plotting")
  }
  thispng <- readPNG(file, native = TRUE)

  devset <- function() {
    if (grDevices::dev.cur() != eventEnv$which) grDevices::dev.set(eventEnv$which)
  }
  drawPage <- function() {
    graphics::plot(c(0, dims[1]), c(0, dims[2]), type = "n", xlab = "", ylab = "", asp = 1)
    graphics::rasterImage(thispng, 0, 0, dims[1], dims[2])
  }
  drawRectangle <- function() {
    if (!is.null(endx)) {
      graphics::rect(startx, starty, endx, endy, col = grDevices::rgb(1, 0, 0, .2))
    }
  }

  mousedown <- function(buttons, x, y) {
    devset()
    if (clicked) {
      endx <<- graphics::grconvertX(x, deviceUnits, "user")
      endy <<- graphics::grconvertY(y, deviceUnits, "user")
      clicked <<- FALSE
      eventEnv$onMouseMove <- NULL
    } else {
      startx <<- graphics::grconvertX(x, deviceUnits, "user")
      starty <<- graphics::grconvertY(y, deviceUnits, "user")
      clicked <<- TRUE
      eventEnv$onMouseMove <- dragmousemove
    }
    NULL
  }
  dragmousemove <- function(buttons, x, y) {
    devset()
    if (clicked) {
      endx <<- graphics::grconvertX(x, deviceUnits, "user")
      endy <<- graphics::grconvertY(y, deviceUnits, "user")
      drawPage()
      drawRectangle()
    }
    NULL
  }
  keydown <- function(key) {
    devset()
    eventEnv$onMouseMove <- NULL
    lastkey <<- key
    TRUE
  }

  pre_par <- graphics::par(mar = c(0, 0, 0, 0), xaxs = "i", yaxs = "i", bty = "n")
  on.exit(graphics::par(pre_par), add = TRUE)
  drawPage()
  on.exit(grDevices::dev.off(), add = TRUE)

  clicked <- FALSE
  lastkey <- NA_character_
  if (!length(area)) {
    startx <- NULL
    starty <- NULL
    endx <- NULL
    endy <- NULL
  } else {
    showArea <- function() {
      # convert from: top,left,bottom,right
      startx <<- area[2]
      starty <<- dims[2] - area[1]
      endx <<- area[4]
      endy <<- dims[2] - area[3]
      drawRectangle()
    }
    showArea()
  }

  p <- "Click and drag to select a table area. Press <Right> for next page or <Q> to quit."
  grDevices::setGraphicsEventHandlers(
    prompt = p,
    onMouseDown = mousedown,
    onKeybd = keydown
  )
  eventEnv <- grDevices::getGraphicsEventEnv()
  grDevices::getGraphicsEvent()

  backToPageSize <- function() {
    # convert to: top,left,bottom,right
    if (!is.null(startx)) {
      c(
        top = dims[2] - max(c(starty, endy)),
        left = min(c(startx, endx)),
        bottom = dims[2] - (min(c(starty, endy))),
        right = max(c(startx, endx))
      )
    } else {
      NULL
    }
  }
  return(list(key = lastkey, area = backToPageSize()))
}
leeper/tabulizer documentation built on Sept. 24, 2024, 11:08 p.m.