📄 tickset_g.class
字号:
// tickset_g
//
// View for a set of ticks and their labels
//
// Note, tightly linked to axis.class and not much use without that class.
// Note, the max and min for ticksets should be set through the _set_xyz_min
// programs provided in axis_g.class.
// consider about convert_custom to convert the current ticks to the
// (axis-level?) custom ticklist.
*! version 1.0.11 18mar2004
version 8
class {
use_rule = .yesno.new , style(no)
min = 1e300 // for the rule
max = -1e300 // for the rule
delta = 1 // for the rule
label_format = "%8.0gc"
ticks = {} // specified ticks
_create_as_custom = .yesno.new , style(no)
_tmin = 1e300 // ticks min
_tmax = -1e300 // ticks max
// see .overallmin/max
_between_ticks = 0 // # of between ticks
_default = 1 // mainly for by()
class scale scale
called = 0
} , inherit(subview)
// ---------------------------------------------------------------------------
// Set the scale used by this tickset.
program set_scale
.scale.ref = .`0'.ref
end
// ---------------------------------------------------------------------------
// Set the min and max and the actual number of ticks and return the set
// min and max
program set_ticks , rclass
args min0 max0 tryticks only_defaults
if "`only_defaults'" != "" & ! `._default' {
exit
}
if `min0' >= `max0' {
.min = 0`min0' - 1
.max = 0`min0' + 1
.delta = `.max' - `.min'
.scale.addcur `.min' `.max'
.use_rule.set_`=cond(0`tryticks' >= 1, "true", "false")'
exit
}
if 0`tryticks' > 1 {
if substr(`"`.label_format'"',1,3) == "%-t" {
local ff = substr(`"`.label_format'"',4,1)
}
else if substr(`"`.label_format'"',1,2) == "%t" {
local ff = substr(`"`.label_format'"',3,1)
}
else if substr(`"`.label_format'"',1,3) == "%-d" {
local ff d
}
else if substr(`"`.label_format'"',1,2) == "%d" {
local ff d
}
if inlist("`ff'","d","w","m","q","h","y") {
gdi tsnatscale `min0' `max0' `tryticks', `ff'
if abs(r(n)) < 10000 {
.min = r(min)
.max = r(max)
if !missing(r(delta)) {
.delta = r(delta)
}
else {
.delta = 0
.add_ticks `r(list)' , clear
}
}
else {
.min = `min0'
.max = `max0'
.delta = `.max' - `.min'
}
}
else {
gdi natscale `min0' `max0' `tryticks'
if abs(r(n)) < 10000 {
.min = r(min)
.max = r(max)
.delta = r(delta)
}
else {
.min = `min0'
.max = `max0'
.delta = `.max' - `.min'
}
}
.use_rule.set_true
// may want a way to force numticks to make
// min and max be inclusive of data range
}
else {
if 0`tryticks' == 1 {
local hold_default 0`._default'
.minmax_ticks
._default = `hold_default'
}
else {
.min = `min0'
.max = `max0'
.delta = `.max' - `.min'
.use_rule.set_false
}
}
end
// ---------------------------------------------------------------------------
program set_format
if `"`0'"' != `""' {
.label_format = `"`0'"'
}
end
// ---------------------------------------------------------------------------
// Set transform.
program set_transform
if "`.scale.transform.stylename'" == "linear" {
exit
}
if `.delta' == 0 {
exit
}
forvalues z = `.min'(`.delta')`.max' {
if `z' > 0 {
.min = `z'
continue, break // Break
}
}
end
// ---------------------------------------------------------------------------
program set_default
confirm number `1'
._default = `1'
end
// ---------------------------------------------------------------------------
program clear_ticks
while 0`.ticks.arrnels' > 0 {
.ticks.Arrpop
}
._tmin = 1e300
._tmax = -1e300
end
program clear
.use_rule.set_false
.min = 1e300
.max = -1e300
.clear_ticks
end
// ---------------------------------------------------------------------------
program _tick_and_label_width
args style ord labseries
if `.ticks.arrnels'==0 & !0`.use_rule.istrue' {
class exit = 0
}
local angle = `.`style'.tickangle.val' - ("`ord'"=="x")*90
if mod(`angle', 180) == 0 { // avoid search through ticks
local biglab "X"
}
else {
local biglab ///
`._longest_label "`labseries'" `.`style'.use_labels.istrue''
}
local size = `.`style'.tickstyle.size `angle' `biglab''
if `.`style'.alternate.istrue' {
local size = `size' + 0`.`style'.alternate_gap.gmval' + ///
`.`style'.tickstyle.textstyle.size.gmval'
}
if mod(`angle', 180) == 0 { // consider multiline
local ct = 0`._max_multi_height `.`style'.use_labels.istrue''
local ht = `ct' * `.`style'.tickstyle.textstyle.size.val' + ///
(`ct'-1) * 0`.`style'.tickstyle.textstyle.linegap.val' + ///
`.`style'.tickstyle.tick_and_gap'
local size = max(`size', `ht')
}
class exit = `size'
end
program _longest_label
args labseries uselbl
local max 0
local fmt `.label_format'
if 0`.use_rule.istrue' & `.delta' != 0 { // min/max/delta
forvalues x = `.min'(`.delta')`.max' {
if 0`uselbl' {
local xstr `"`.`labseries'.value_label `x' `fmt''"'
}
if !`uselbl' | `"`xstr'"' == `""' {
local xstr = string(`x',`"`fmt'"')
}
if length(`"`xstr'"') > `max' {
local maxstr `"`xstr'"'
local max = length(`"`xstr'"')
}
}
local xstr = string(`.max',`"`fmt'"')
if length(`"`xstr'"') > `max' {
local maxstr `"`xstr'"'
local max = length(`"`xstr'"')
}
}
forvalues i = 1/0`.ticks.arrnels' { // custom
local x `.ticks[`i'][1]'
local lab
if `"`.ticks[`i'][2]'"' == `""' {
if `uselbl' {
local lab `"`.`labseries'.value_label `x' `fmt''"'
}
if !`uselbl' | `"`lab'"' == `""' {
local lab `=string(`x',"`fmt'")'
}
}
else {
local lab `"`.ticks[`i'][2]'"'
gettoken chk1 chk2 : lab , qed(quoted)
if `quoted' & `"`chk2'"' != `""' {
local lab `"`chk1'"'
while `"`chk2'"' != `""' {
gettoken chk1 chk2 : chk2
if length(`"`chk1'"') > length(`"`lab'"') {
local lab `"`chk1'"'
}
}
}
}
if length(`"`lab'"') > `max' {
local maxstr `"`lab'"'
local max = length(`"`maxstr'"')
}
}
class exit `"`maxstr'"'
end
program _max_multi_height
args uselbl
local fmt `.label_format' // 01jul2003 -- jsp added
local maxct 0
forvalues i = 1/0`.ticks.arrnels' {
local lab `"`.ticks[`i'][2]'"'
if `"`lab'"' == `""' {
if 0`uselbl' {
local labels `._value_label_series'
local lab `"`.`labels'.value_label `.ticks[`i'][1]' `fmt''"'
}
}
if `"`lab'"' != `""' {
gettoken chk1 chk2 : lab , qed(quoted)
if `quoted' & `"`chk2'"' != `""' {
local ct 1
while `"`chk2'"' != `""' {
gettoken chk1 chk2 : chk2
if ( `"`chk1'"' != `""' ) local ++ct
}
}
local maxct = max(`maxct', `ct')
}
}
class exit = `maxct'
end
program _value_label_series
local axis : word 1 of `.scale.axes'
local ord = cond("`.`axis'.position.snm'"=="left" | ///
"`.`axis'.position.snm'"=="right", "y", "x")
class exit "`.`axis'.plotregion.dynamicmv[1].dim_value_label_series `ord''"
// ^
// usually plot1
end
// ---------------------------------------------------------------------------
// Sets the rule for the tickset using natscale and the suggested number of
// ticks and the current min and max from the scale.
//
// Usage: suggest_ticks_current <#_suggested_number_of_ticks>
program suggest_ticks_current
args ticks
capture confirm integer number `ticks'
if _rc {
di as error `"invalid tick rule, `ticks' not an integer"'
exit 198
}
.set_ticks `.scale.curmin' `.scale.curmax' `ticks'
._between_ticks = 0
.use_rule.set_true
end
// ---------------------------------------------------------------------------
// Sets the rule for the tickset using natscale and the suggested number of
// ticks and the absolute min and max from the scale.
//
// Usage: suggest_ticks <#_suggested_number_of_ticks>
program suggest_ticks
args ticks
capture confirm integer number `ticks'
if _rc {
di as error `"invalid tick rule, `ticks' not an integer"'
exit 198
}
.set_ticks `.scale.min' `.scale.max' `ticks'
._between_ticks = 0
.use_rule.set_true
end
program suggest_between_ticks
args ticks
if `ticks' < 1 {
exit
}
if ! 0`.mymajor.isofclass tickset_g' {
di in green "##`ticks' ignored, only allowed for minor ticks"
exit
}
.delta = `.mymajor.delta' / max(`ticks', 1)
.min = min(`.scale.min', `.scale.curmin')
.max = max(`.scale.max', `.scale.curmax')
.min = `.mymajor.min' - ///
`.delta' * floor((`.mymajor.min' - `.min') / `.delta')
.max = `.mymajor.max' + ///
`.delta' * floor((`.max' - `.mymajor.max') / `.delta')
._between_ticks = `ticks'
.use_rule.set_true
end
program reset_between_ticks
.suggest_between_ticks `._between_ticks'
end
// ---------------------------------------------------------------------------
// Sets the rule for the tickset to be a single tick at the absolute minium
// and maximum of the scale.
//
// Usage: minmax_ticks
program minmax_ticks
.min = `.scale.min'
.max = `.scale.max'
.delta = `.max' - `.min'
._between_ticks = 0
.use_rule.set_true
._default = 0
end
program none_ticks
._between_ticks = 0
.use_rule.set_false
._default = 0
end
program range_ticks
local fmt `.label_format'
_date2elapsed, format(`fmt') datelist()
if "`s(fmt)'" == "" {
gettoken min 0 : 0
gettoken max 0 : 0
gettoken delta 0 : 0
}
else {
gettoken min 0 : 0 , parse(" ()") match(par1)
gettoken max 0 : 0 , parse(" ()") match(par2)
gettoken delta 0 : 0
_date2elapsed, format(`fmt') datelist((`min'))
local dmin `s(args)'
capture numlist "`dmin'", min(1) max(1)
if _rc {
di as err ///
`"invalid tick rule,"' ///
`"`min' must be a number or valid argument for `s(fmt)'() function"'
exit 198
}
_date2elapsed, format(`fmt') datelist((`max'))
local dmax `s(args)'
capture numlist "`dmax'", min(1) max(1)
if _rc {
di as err ///
`"invalid tick rule,"' ///
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -