style.go (5466B)
1 // Copyright 2024 The TCell Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use file except in compliance with the License. 5 // You may obtain a copy of the license at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tcell 16 17 // Style represents a complete text style, including both foreground color, 18 // background color, and additional attributes such as "bold" or "underline". 19 // 20 // Note that not all terminals can display all colors or attributes, and 21 // many might have specific incompatibilities between specific attributes 22 // and color combinations. 23 // 24 // To use Style, just declare a variable of its type. 25 type Style struct { 26 fg Color 27 bg Color 28 ulStyle UnderlineStyle 29 ulColor Color 30 attrs AttrMask 31 url string 32 urlId string 33 } 34 35 // StyleDefault represents a default style, based upon the context. 36 // It is the zero value. 37 var StyleDefault Style 38 39 // styleInvalid is just an arbitrary invalid style used internally. 40 var styleInvalid = Style{attrs: AttrInvalid} 41 42 // Foreground returns a new style based on s, with the foreground color set 43 // as requested. ColorDefault can be used to select the global default. 44 func (s Style) Foreground(c Color) Style { 45 s2 := s 46 s2.fg = c 47 return s2 48 } 49 50 // Background returns a new style based on s, with the background color set 51 // as requested. ColorDefault can be used to select the global default. 52 func (s Style) Background(c Color) Style { 53 s2 := s 54 s2.bg = c 55 return s2 56 } 57 58 // Decompose breaks a style up, returning the foreground, background, 59 // and other attributes. The URL if set is not included. 60 // Deprecated: Applications should not attempt to decompose style, 61 // as this content is not sufficient to describe the actual style. 62 func (s Style) Decompose() (fg Color, bg Color, attr AttrMask) { 63 return s.fg, s.bg, s.attrs 64 } 65 66 func (s Style) setAttrs(attrs AttrMask, on bool) Style { 67 s2 := s 68 if on { 69 s2.attrs |= attrs 70 } else { 71 s2.attrs &^= attrs 72 } 73 return s2 74 } 75 76 // Normal returns the style with all attributes disabled. 77 func (s Style) Normal() Style { 78 return Style{ 79 fg: s.fg, 80 bg: s.bg, 81 } 82 } 83 84 // Bold returns a new style based on s, with the bold attribute set 85 // as requested. 86 func (s Style) Bold(on bool) Style { 87 return s.setAttrs(AttrBold, on) 88 } 89 90 // Blink returns a new style based on s, with the blink attribute set 91 // as requested. 92 func (s Style) Blink(on bool) Style { 93 return s.setAttrs(AttrBlink, on) 94 } 95 96 // Dim returns a new style based on s, with the dim attribute set 97 // as requested. 98 func (s Style) Dim(on bool) Style { 99 return s.setAttrs(AttrDim, on) 100 } 101 102 // Italic returns a new style based on s, with the italic attribute set 103 // as requested. 104 func (s Style) Italic(on bool) Style { 105 return s.setAttrs(AttrItalic, on) 106 } 107 108 // Reverse returns a new style based on s, with the reverse attribute set 109 // as requested. (Reverse usually changes the foreground and background 110 // colors.) 111 func (s Style) Reverse(on bool) Style { 112 return s.setAttrs(AttrReverse, on) 113 } 114 115 // StrikeThrough sets strikethrough mode. 116 func (s Style) StrikeThrough(on bool) Style { 117 return s.setAttrs(AttrStrikeThrough, on) 118 } 119 120 // Underline style. Modern terminals have the option of rendering the 121 // underline using different styles, and even different colors. 122 type UnderlineStyle int 123 124 const ( 125 UnderlineStyleNone = UnderlineStyle(iota) 126 UnderlineStyleSolid 127 UnderlineStyleDouble 128 UnderlineStyleCurly 129 UnderlineStyleDotted 130 UnderlineStyleDashed 131 ) 132 133 // Underline returns a new style based on s, with the underline attribute set 134 // as requested. The parameters can be: 135 // 136 // bool: on / off - enables just a simple underline 137 // UnderlineStyle: sets a specific style (should not coexist with the bool) 138 // Color: the color to use 139 func (s Style) Underline(params ...interface{}) Style { 140 s2 := s 141 for _, param := range params { 142 switch v := param.(type) { 143 case bool: 144 if v { 145 s2.ulStyle = UnderlineStyleSolid 146 s2.attrs |= AttrUnderline 147 } else { 148 s2.ulStyle = UnderlineStyleNone 149 s2.attrs &^= AttrUnderline 150 } 151 case UnderlineStyle: 152 if v == UnderlineStyleNone { 153 s2.attrs &^= AttrUnderline 154 } else { 155 s2.attrs |= AttrUnderline 156 } 157 s2.ulStyle = v 158 case Color: 159 s2.ulColor = v 160 default: 161 panic("Bad type for underline") 162 } 163 } 164 return s2 165 } 166 167 // Attributes returns a new style based on s, with its attributes set as 168 // specified. 169 func (s Style) Attributes(attrs AttrMask) Style { 170 s2 := s 171 s2.attrs = attrs 172 return s2 173 } 174 175 // Url returns a style with the Url set. If the provided Url is not empty, 176 // and the terminal supports it, text will typically be marked up as a clickable 177 // link to that Url. If the Url is empty, then this mode is turned off. 178 func (s Style) Url(url string) Style { 179 s2 := s 180 s2.url = url 181 return s2 182 } 183 184 // UrlId returns a style with the UrlId set. If the provided UrlId is not empty, 185 // any marked up Url with this style will be given the UrlId also. If the 186 // terminal supports it, any text with the same UrlId will be grouped as if it 187 // were one Url, even if it spans multiple lines. 188 func (s Style) UrlId(id string) Style { 189 s2 := s 190 s2.urlId = "id=" + id 191 return s2 192 }