Skip to content

Commit

Permalink
Fixes Open-Systems-Pharmacology#234 add alignment as property of labe…
Browse files Browse the repository at this point in the history
…l objects

Also fixes font family property in the process
  • Loading branch information
pchelle committed Apr 21, 2022
1 parent 389aadf commit bf2ef84
Show file tree
Hide file tree
Showing 19 changed files with 364 additions and 109 deletions.
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export(AestheticProperties)
export(AestheticSelectionKeys)
export(AggregationInput)
export(AggregationSummary)
export(Alignments)
export(AxisConfiguration)
export(BackgroundConfiguration)
export(BackgroundElement)
Expand All @@ -43,6 +44,7 @@ export(DDIRatioDataMapping)
export(DDIRatioPlotConfiguration)
export(ExportConfiguration)
export(Font)
export(FontFaces)
export(GroupMapping)
export(Grouping)
export(HistogramDataMapping)
Expand Down
160 changes: 106 additions & 54 deletions R/font.R
Original file line number Diff line number Diff line change
@@ -1,54 +1,106 @@
#' @title Font
#' @description R6 class defining font properties
#' @field size numeric defining the size of font
#' @field color character defining the color of font
#' @field fontFamily character defining the family of font
#' @field fontFace character defining the face of font
#' @field angle numeric defining the angle of font
#' @export
Font <- R6::R6Class(
"Font",
public = list(
size = 12,
color = "black",
fontFamily = "",
fontFace = "plain",
angle = 0,

#' @description Create a new `Font` object.
#' Default font properties are defined directly in the object field,
#' so `NULL` input is allowed will lead to default properties.
#' @param size numeric defining the size of font
#' @param color character defining the color of font
#' @param fontFamily character defining the family of font
#' @param fontFace character defining the face of font
#' @param angle numeric defining the angle of font
#' @return A new `Font` object
initialize = function(size = NULL,
color = NULL,
fontFamily = NULL,
fontFace = NULL,
angle = NULL) {
validateIsString(c(color, fontFamily, fontFace), nullAllowed = TRUE)
validateIsNumeric(c(size, angle), nullAllowed = TRUE)
eval(parseVariableToObject("self", c("size", "color", "fontFace", "fontFamily", "angle"), keepIfNull = TRUE))
},

#' @description Create a `ggplot2::element_text` directly convertible by `ggplot2::theme`.
#' @return An `element_text` object.
createPlotFont = function() {
ggplot2::element_text(
colour = self$color,
size = self$size,
face = self$fontFace,
# TODO: check why I get the following error messages
# "font family not found in Windows font database"
# family = self$fontFamily,
angle = self$angle,
# Center the label even with angle
vjust = 0.5,
hjust = 0.5
)
}
)
)
#' @title Font
#' @description R6 class defining font properties
#' @field size numeric defining the size of font
#' @field color character defining the color of font
#' @field fontFamily character defining the family of font
#' @field fontFace character defining the font face as defined in helper enum `FontFaces`.
#' @field angle numeric defining the angle of font
#' @field align character defining the alignment of font as defined in helper enum `Alignments`.
#' @export
Font <- R6::R6Class(
"Font",
public = list(
size = 12,
color = "black",
fontFamily = "",
fontFace = "plain",
angle = 0,
align = "center",

#' @description Create a new `Font` object.
#' Default font properties are defined directly in the object field,
#' so `NULL` input is allowed will lead to default properties.
#' @param color character defining the color of font
#' @param size numeric defining the size of font
#' @param fontFamily character defining the family of font
#' @param fontFace character defining the font face as defined in helper enum `FontFaces`.
#' @param angle numeric defining the angle of font
#' @param align character defining the alignment of font as defined in helper enum `Alignments`.
#' @return A new `Font` object
initialize = function(color = NULL,
size = NULL,
fontFamily = NULL,
fontFace = NULL,
angle = NULL,
align = NULL) {
validateIsString(c(color, fontFamily), nullAllowed = TRUE)
validateIsNumeric(c(size, angle), nullAllowed = TRUE)
validateIsIncluded(fontFace, FontFaces, nullAllowed = TRUE)
validateIsIncluded(align, Alignments, nullAllowed = TRUE)
eval(parseVariableToObject("self", c("size", "color", "fontFace", "fontFamily", "angle", "align"), keepIfNull = TRUE))
},

#' @description Create a `ggplot2::element_text` directly convertible by `ggplot2::theme`.
#' @param size numeric defining the size of font
#' @param color character defining the color of font
#' @param fontFamily character defining the family of font
#' @param fontFace character defining the font face as defined in helper enum `FontFaces`.
#' @param angle numeric defining the angle of font
#' @param align character defining the alignment of font as defined in helper enum `Alignments`.
#' @return An `element_text` object.
createPlotFont = function(size = NULL,
color = NULL,
fontFamily = NULL,
fontFace = NULL,
angle = NULL,
align = NULL) {
ggplot2::element_text(
colour = color %||% self$color,
size = size %||% self$size,
face = fontFace %||% self$fontFace,
# Use font family only if available in Windows font database database
family = checkPlotFontFamily(fontFamily %||% self$fontFamily),
angle = angle %||% self$angle,
vjust = 0.5,
hjust = switch(align %||% self$align, "left" = 0, "center" = 0.5, "right" = 1)
)
}
)
)

#' @title Alignments
#' @import ospsuite.utils
#' @export
#' @description
#' List of all available alignments/justifications for fonts
#' @family enum helpers
Alignments <- enum(c("left", "center","right"))

#' @title FontFaces
#' @import ospsuite.utils
#' @export
#' @description
#' List of all available font faces
#' @family enum helpers
FontFaces <- enum(c("plain", "bold", "italic", "bold.italic"))


#' @title checkPlotFontFamily
#' @description Check if font family is available in Windows font database.
#' Use function `grDevices::windowsFonts()` to get the list of font families available.
#' @param fontFamily character defining the family of font
#' @return Name of font family if available in Windows font database
#' `NULL` otherwise
#' @keywords internal
checkPlotFontFamily <- function(fontFamily){
if(isEmpty(.Platform$OS.type)){
return(NULL)
}
if(.Platform$OS.type != "windows"){
return(NULL)
}
if(isIncluded(fontFamily, names(grDevices::windowsFonts()))){
return(fontFamily)
}
return(NULL)
}
49 changes: 35 additions & 14 deletions R/label.R
Original file line number Diff line number Diff line change
@@ -1,42 +1,63 @@
#' @title Label
#' @description R6 class defining `text` and `font` of label
#' @description R6 class defining `text` and `font` of labels
#' @export
Label <- R6::R6Class(
"Label",
public = list(
#' @description Create a new `Label` object.
#' @param text character text of the `Label` object
#' @param font `Font` object defining the font of the `Label` object
#' @param size numeric defining the size of the `Label` object
#' @param color character defining the color of the `Label` object
#' @param fontFamily character defining the font family of the `Label` object
#' @param fontFace character defining the font face of the `Label` object
#' @param angle numeric defining the angle of the `Label` object
#' @param text character text of the label
#' @param font `Font` object defining the font of the label
#' @param size numeric defining the size of the label
#' @param color character defining the color of the label
#' @param fontFamily character defining the font family of the label
#' @param fontFace character defining the font face of the label as defined in helper enum `FontFaces`.
#' @param angle numeric defining the angle of the label
#' @param align character defining the alignment of the label as defined in helper enum `Alignments`.
#' @return A new `Label` object
initialize = function(text = "",
font = NULL,
color = NULL,
size = NULL,
fontFace = NULL,
fontFamily = NULL,
angle = NULL) {
angle = NULL,
align = NULL) {
validateIsNumeric(c(as.numeric(angle), as.numeric(size)), nullAllowed = TRUE)
validateIsString(c(color, fontFace, fontFamily), nullAllowed = TRUE)
validateIsString(c(color, fontFamily), nullAllowed = TRUE)
validateIsOfType(font, "Font", nullAllowed = TRUE)
validateIsIncluded(fontFace, FontFaces, nullAllowed = TRUE)
validateIsIncluded(align, Alignments, nullAllowed = TRUE)

self$text <- text
self$font <- font %||% Font$new()
# If font properties are explicitely written, they will overwrite the properties of input Font
eval(parseVariableToObject("self$font", c("size", "color", "fontFace", "fontFamily", "angle"), keepIfNull = TRUE))
eval(parseVariableToObject("self$font", c("size", "color", "fontFace", "fontFamily", "angle", "align"), keepIfNull = TRUE))
},

#' @description Create a `ggplot2::element_text` directly convertible by `ggplot2::theme`.
#' @param size numeric defining the size of the label
#' @param color character defining the color of the label
#' @param fontFamily character defining the font family of the label
#' @param fontFace character defining the font face of the label as defined in helper enum `FontFaces`.
#' @param angle numeric defining the angle of the label
#' @param align character defining the alignment of the label as defined in helper enum `Alignments`.
#' @return An `element_text` or `element_blank`object.
createPlotFont = function() {
if (isOfLength(self$text, 0)) {
createPlotFont = function(color = NULL,
size = NULL,
fontFace = NULL,
fontFamily = NULL,
angle = NULL,
align = NULL) {
if (isEmpty(self$text)) {
return(ggplot2::element_blank())
}
return(self$font$createPlotFont())
return(self$font$createPlotFont(
color = color,
size = size,
fontFace = fontFace,
fontFamily = fontFamily,
angle = angle,
align = align))
}
),
active = list(
Expand Down
20 changes: 16 additions & 4 deletions R/plotconfiguration-label.R
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ LabelConfiguration <- R6::R6Class(
return(private$.title)
}
validateIsOfType(value, c("character", "Label"), nullAllowed = TRUE)
private$.title <- asLabel(value)
if(isOfType(value, "Label")){
private$.title <- asLabel(value)
}
private$.title <- asLabel(value, font = private$.title$font)
return(invisible())
},
#' @field subtitle `Label` object defining the subtitle of the plot
Expand All @@ -66,7 +69,10 @@ LabelConfiguration <- R6::R6Class(
return(private$.subtitle)
}
validateIsOfType(value, c("character", "Label"), nullAllowed = TRUE)
private$.subtitle <- asLabel(value)
if(isOfType(value, "Label")){
private$.subtitle <- asLabel(value)
}
private$.subtitle <- asLabel(value, font = private$.subtitle$font)
return(invisible())
},
#' @field xlabel `Label` object defining the xlabel of the plot
Expand All @@ -75,7 +81,10 @@ LabelConfiguration <- R6::R6Class(
return(private$.xlabel)
}
validateIsOfType(value, c("character", "Label"), nullAllowed = TRUE)
private$.xlabel <- asLabel(value)
if(isOfType(value, "Label")){
private$.xlabel <- asLabel(value)
}
private$.xlabel <- asLabel(value, font = private$.xlabel$font)
return(invisible())
},
#' @field ylabel `Label` object defining the ylabel of the plot
Expand All @@ -84,7 +93,10 @@ LabelConfiguration <- R6::R6Class(
return(private$.ylabel)
}
validateIsOfType(value, c("character", "Label"), nullAllowed = TRUE)
private$.ylabel <- asLabel(value)
if(isOfType(value, "Label")){
private$.ylabel <- asLabel(value)
}
private$.ylabel <- asLabel(value, font = private$.ylabel$font)
return(invisible())
}
),
Expand Down
2 changes: 1 addition & 1 deletion R/plotconfiguration.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ PlotConfiguration <- R6::R6Class(
#' @param panelArea `BackgroundElement` object defining properties of panel area
#' @param xGrid `LineElement` object defining properties of x-grid background
#' @param yGrid `LineElement` object defining properties of y-grid background
#' @param watermark `Label` object defining watermark
#' @param watermark character or `Label` object defining watermark
#' @param export R6 class `ExportConfiguration` defining properties for saving/exporting plota
#' @param name character defining the name of the file to be saved (without extension)
#' @param format character defining the format of the file to be saved.
Expand Down
39 changes: 23 additions & 16 deletions R/themes.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ ThemeFont <- R6::R6Class(
#' @param xlabel `Font` object or list for font properties of xlabel
#' @param ylabel `Font` object or list for font properties of ylabel
#' @param watermark `Font` object or list for font properties of watermark
#' @param legendTitle `Font` object or list for font properties of legend
#' @param legendTitle `Font` object or list for font properties of legend title
#' @param legend `Font` object or list for font properties of legend
#' @param xAxis `Font` object or list for font properties of xAxis
#' @param yAxis `Font` object or list for font properties of yAxis
#' @param baseColor name of base color of undefined fonts. Default is black.
#' @param baseColor name of base color of undefined fonts. Default is "black".
#' @param baseSize base size of undefined fonts. Default is 12.
#' @param baseFace name of base face of undefined fonts. Default is "plain".
#' @param baseFamily name of base family of undefined fonts. Default is "".
#' @param baseAngle base angle of undefined fonts. Default is 0 degree.
#' @param baseAlign base alignment of undefined fonts. Default is "center".
#' @return A new `ThemeFont` object
initialize = function(title = NULL,
subtitle = NULL,
Expand All @@ -54,22 +55,26 @@ ThemeFont <- R6::R6Class(
baseSize = 12,
baseFace = "plain",
baseFamily = "",
baseAngle = 0) {
baseAngle = 0,
baseAlign = "center") {
# Validate necessary input
validateIsString(baseColor)
validateIsString(baseFace)
validateIsString(baseFamily)
validateIsNumeric(baseSize)
validateIsNumeric(baseAngle)
validateIsIncluded(baseFace, FontFaces)
validateIsIncluded(baseAlign, Alignments)

# Create all field properties by parsing and evaluating their expression
fieldNames <- c("title", "subtitle", "xlabel", "ylabel", "watermark", "legendTitle", "legend", "xAxis", "yAxis")
setFontExpression <- parse(text = paste0("self$", fieldNames, " <- Font$new(
color = ", fieldNames, "$color %||% baseColor,
size = ", fieldNames, "$size %||% baseSize,
fontFace = ", fieldNames, "$fontFace %||% baseFace,
fontFamily = ", fieldNames, "$fontFamily %||% baseFamily,
angle = ", fieldNames, "$angle %||% baseAngle)"))
setFontExpression <- parse(text = paste0(
"self$", fieldNames, " <- Font$new(",
"color = ", fieldNames, "$color %||% baseColor,",
"size = ", fieldNames, "$size %||% baseSize,",
"fontFace = ", fieldNames, "$fontFace %||% baseFace,",
"fontFamily = ", fieldNames, "$fontFamily %||% baseFamily,",
"angle = ", fieldNames, "$angle %||% baseAngle,",
"align = ", fieldNames, "$align %||% baseAlign)"))
eval(setFontExpression)
},

Expand All @@ -78,12 +83,14 @@ ThemeFont <- R6::R6Class(
toJson = function() {
jsonObject <- list()
fieldNames <- c("title", "subtitle", "xlabel", "ylabel", "watermark", "legendTitle", "legend", "xAxis", "yAxis")
setJsonExpression <- parse(text = paste0("jsonObject$", fieldNames, " <- list(
color = self$", fieldNames, "$color,
size = self$", fieldNames, "$size,
angle = self$", fieldNames, "$angle,
fontFace = self$", fieldNames, "$fontFace,
fontFamily = self$", fieldNames, "$fontFamily)"))
setJsonExpression <- parse(text = paste0(
"jsonObject$", fieldNames, " <- list(",
"color = self$", fieldNames, "$color,",
"size = self$", fieldNames, "$size,",
"angle = self$", fieldNames, "$angle,",
"align = self$", fieldNames, "$align,",
"fontFace = self$", fieldNames, "$fontFace,",
"fontFamily = self$", fieldNames, "$fontFamily)"))
eval(setJsonExpression)
return(jsonObject)
}
Expand Down
2 changes: 2 additions & 0 deletions man/AestheticProperties.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bf2ef84

Please sign in to comment.